home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / mbyte.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-26  |  98.6 KB  |  4,029 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  * Multibyte extensions partly by Sung-Hoon Baek
  5.  *
  6.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  7.  * Do ":help credits" in Vim to see a list of people who contributed.
  8.  * See README.txt for an overview of the Vim source code.
  9.  */
  10. /*
  11.  * mbyte.c: Code specifically for handling multi-byte characters.
  12.  *
  13.  * The encoding used in the core is set with 'encoding'.  When 'encoding' is
  14.  * changed, the following four variables are set (for speed).
  15.  * Currently these types of character encodings are supported:
  16.  *
  17.  * "enc_dbcs"        When non-zero it tells the type of double byte character
  18.  *            encoding (Chinese, Korean, Japanese, etc.).
  19.  *            The cell width on the display is equal to the number of
  20.  *            bytes.  (exception: DBCS_JPNU with first byte 0x8e)
  21.  *            Recognizing the first or second byte is difficult, it
  22.  *            requires checking a byte sequence from the start.
  23.  * "enc_utf8"        When TRUE use Unicode characters in UTF-8 encoding.
  24.  *            The cell width on the display needs to be determined from
  25.  *            the character value.
  26.  *            Recognizing bytes is easy: 0xxx.xxxx is a single-byte
  27.  *            char, 10xx.xxxx is a trailing byte, 11xx.xxxx is a leading
  28.  *            byte of a multi-byte character.
  29.  *            To make things complicated, up to two composing characters
  30.  *            are allowed.  These are drawn on top of the first char.
  31.  *            For most editing the sequence of bytes with composing
  32.  *            characters included is considered to be one character.
  33.  * "enc_unicode"    When 2 use 16-bit Unicode characters (or UTF-16).
  34.  *            When 4 use 32-but Unicode characters.
  35.  *            Internally characters are stored in UTF-8 encoding to
  36.  *            avoid NUL bytes.  Conversion happens when doing I/O.
  37.  *            "enc_utf8" will also be TRUE.
  38.  *
  39.  * "has_mbyte" is set when "enc_dbcs" or "enc_utf8" is non-zero.
  40.  *
  41.  * If none of these is TRUE, 8-bit bytes are used for a character.  The
  42.  * encoding isn't currently specified (TODO).
  43.  *
  44.  * 'encoding' specifies the encoding used in the core.  This is in registers,
  45.  * text manipulation, buffers, etc.  Conversion has to be done when characters
  46.  * in another encoding are received or send:
  47.  *
  48.  *               clipboard
  49.  *               ^
  50.  *               | (2)
  51.  *               V
  52.  *           +---------------+
  53.  *          (1)  |           | (3)
  54.  *  keyboard ----->|     core       |-----> display
  55.  *           |           |
  56.  *           +---------------+
  57.  *               ^
  58.  *               | (4)
  59.  *               V
  60.  *             file
  61.  *
  62.  * (1) Typed characters arrive in the current locale.  Conversion is to be
  63.  *     done when 'encoding' is different from 'termencoding'.
  64.  * (2) Text will be made available with the encoding specified with
  65.  *     'encoding'.  If this is not sufficient, system-specific conversion
  66.  *     might be required.
  67.  * (3) For the GUI the correct font must be selected, no conversion done.
  68.  *     Otherwise, conversion is to be done when 'encoding' differs from
  69.  *     'termencoding'.
  70.  * (4) The encoding of the file is specified with 'fileencoding'.  Conversion
  71.  *     is to be done when it's different from 'encoding'.
  72.  *
  73.  * The viminfo file is a special case: Only text is converted, not file names.
  74.  * Vim scripts may contain an ":encoding" command.  This has an effect for
  75.  * some commands, like ":menutrans"
  76.  */
  77.  
  78. #include "vim.h"
  79.  
  80. #ifdef WIN32UNIX
  81. # ifndef WIN32_LEAN_AND_MEAN
  82. #  define WIN32_LEAN_AND_MEAN
  83. # endif
  84. # include <windows.h>
  85. #endif
  86.  
  87. #if (defined(WIN3264) || defined(WIN32UNIX)) && !defined(__MINGW32__)
  88. # include <winnls.h>
  89. #endif
  90.  
  91. #ifdef FEAT_GUI_X11
  92. # include <X11/Intrinsic.h>
  93. #endif
  94. #ifdef X_LOCALE
  95. #include <X11/Xlocale.h>
  96. #endif
  97. #ifndef EILSEQ
  98. # define EILSEQ 123
  99. #endif
  100.  
  101. #if defined(FEAT_MBYTE) || defined(PROTO)
  102.  
  103. static int dbcs_ptr2len_check __ARGS((char_u *p));
  104. static int dbcs_char2cells __ARGS((int c));
  105. static int dbcs_char2len __ARGS((int c));
  106. static int dbcs_char2bytes __ARGS((int c, char_u *buf));
  107. static int dbcs_ptr2char __ARGS((char_u *p));
  108. static int enc_alias_search __ARGS((char_u *name));
  109.  
  110. /* Lookup table to quickly get the length in bytes of a UTF-8 character from
  111.  * the first byte of a UTF-8 string.  Bytes which are illegal when used as the
  112.  * first byte have a one, because these will be used separately. */
  113. static char utf8len_tab[256] =
  114. {
  115.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  116.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  117.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  118.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  119.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /*bogus*/
  120.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /*bogus*/
  121.     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  122.     3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
  123. };
  124.  
  125. /*
  126.  * Canonical encoding names and their properties.
  127.  * "iso-8859-n" is handled by enc_canonize() directly.
  128.  */
  129. static struct
  130. {   char *name;        int prop;        int codepage;}
  131. enc_canon_table[] =
  132. {
  133. #define IDX_LATIN_1    0
  134.     {"latin1",        ENC_8BIT + ENC_LATIN1,    0},
  135. #define IDX_ISO_2    1
  136.     {"iso-8859-2",    ENC_8BIT,        0},
  137. #define IDX_ISO_3    2
  138.     {"iso-8859-3",    ENC_8BIT,        0},
  139. #define IDX_ISO_4    3
  140.     {"iso-8859-4",    ENC_8BIT,        0},
  141. #define IDX_ISO_5    4
  142.     {"iso-8859-5",    ENC_8BIT,        0},
  143. #define IDX_ISO_6    5
  144.     {"iso-8859-6",    ENC_8BIT,        0},
  145. #define IDX_ISO_7    6
  146.     {"iso-8859-7",    ENC_8BIT,        0},
  147. #define IDX_CP1255    7
  148.     {"cp1255",        ENC_8BIT,        0}, /* close to iso-8859-8 */
  149. #define IDX_ISO_8    8
  150.     {"iso-8859-8",    ENC_8BIT,        0},
  151. #define IDX_ISO_9    9
  152.     {"iso-8859-9",    ENC_8BIT,        0},
  153. #define IDX_ISO_10    10
  154.     {"iso-8859-10",    ENC_8BIT,        0},
  155. #define IDX_ISO_11    11
  156.     {"iso-8859-11",    ENC_8BIT,        0},
  157. #define IDX_ISO_13    12
  158.     {"iso-8859-13",    ENC_8BIT,        0},
  159. #define IDX_ISO_14    13
  160.     {"iso-8859-14",    ENC_8BIT,        0},
  161. #define IDX_ISO_15    14
  162.     {"iso-8859-15",    ENC_8BIT,        0},
  163. #define IDX_KOI8_R    15
  164.     {"koi8-r",        ENC_8BIT,        0},
  165. #define IDX_KOI8_U    16
  166.     {"koi8-u",        ENC_8BIT,        0},
  167. #define IDX_UTF8    17
  168.     {"utf-8",        ENC_UNICODE,        0},
  169. #define IDX_UCS2    18
  170.     {"ucs-2",        ENC_UNICODE + ENC_ENDIAN_B + ENC_2BYTE, 0},
  171. #define IDX_UCS2LE    19
  172.     {"ucs-2le",        ENC_UNICODE + ENC_ENDIAN_L + ENC_2BYTE, 0},
  173. #define IDX_UTF16    20
  174.     {"utf-16",        ENC_UNICODE + ENC_ENDIAN_B + ENC_2WORD, 0},
  175. #define IDX_UTF16LE    21
  176.     {"utf-16le",    ENC_UNICODE + ENC_ENDIAN_L + ENC_2WORD, 0},
  177. #define IDX_UCS4    22
  178.     {"ucs-4",        ENC_UNICODE + ENC_ENDIAN_B + ENC_4BYTE, 0},
  179. #define IDX_UCS4LE    23
  180.     {"ucs-4le",        ENC_UNICODE + ENC_ENDIAN_L + ENC_4BYTE, 0},
  181. #define IDX_DEBUG    24
  182.     {"debug",        ENC_DBCS,        DBCS_DEBUG},
  183. #define IDX_CP932    25
  184.     {"cp932",        ENC_DBCS,        DBCS_JPN},
  185. #define IDX_CP949    26
  186.     {"cp949",        ENC_DBCS,        DBCS_KOR},
  187. #define IDX_CP936    27
  188.     {"cp936",        ENC_DBCS,        DBCS_CHS},
  189. #define IDX_CP950    28
  190.     {"cp950",        ENC_DBCS,        DBCS_CHT},
  191. #define IDX_EUC_JP    29
  192.     {"euc-jp",        ENC_DBCS,        DBCS_JPNU},
  193. #define IDX_SJIS    30
  194.     {"sjis",        ENC_DBCS,        DBCS_JPN},
  195. #define IDX_EUC_KR    31
  196.     {"euc-kr",        ENC_DBCS,        DBCS_KORU},
  197. #define IDX_EUC_CN    32
  198.     {"euc-cn",        ENC_DBCS,        DBCS_CHSU},
  199. #define IDX_EUC_TW    33
  200.     {"euc-tw",        ENC_DBCS,        DBCS_CHTU},
  201. #define IDX_BIG5    34
  202.     {"big5",        ENC_DBCS,        DBCS_CHT},
  203. #define IDX_COUNT    35
  204. };
  205.  
  206. /*
  207.  * Aliases for encoding names.
  208.  */
  209. static struct
  210. {   char *name;        int canon;}
  211. enc_alias_table[] =
  212. {
  213.     {"ansi",        IDX_LATIN_1},
  214.     {"iso-8859-1",    IDX_LATIN_1},
  215.     {"latin2",        IDX_ISO_2},
  216.     {"latin3",        IDX_ISO_3},
  217.     {"latin4",        IDX_ISO_4},
  218.     {"cyrillic",    IDX_ISO_5},
  219.     {"arabic",        IDX_ISO_6},
  220.     {"greek",        IDX_ISO_7},
  221. #ifdef WIN3264
  222.     {"hebrew",        IDX_CP1255},
  223. #else
  224.     {"hebrew",        IDX_ISO_8},
  225. #endif
  226.     {"latin5",        IDX_ISO_9},
  227.     {"turkish",        IDX_ISO_9}, /* ? */
  228.     {"latin6",        IDX_ISO_10},
  229.     {"nordic",        IDX_ISO_10}, /* ? */
  230.     {"thai",        IDX_ISO_11}, /* ? */
  231.     {"latin7",        IDX_ISO_13},
  232.     {"latin8",        IDX_ISO_14},
  233.     {"latin9",        IDX_ISO_15},
  234.     {"utf8",        IDX_UTF8},
  235.     {"unicode",        IDX_UCS2},
  236.     {"ucs2",        IDX_UCS2},
  237.     {"ucs2be",        IDX_UCS2},
  238.     {"ucs-2be",        IDX_UCS2},
  239.     {"ucs2le",        IDX_UCS2LE},
  240.     {"utf16",        IDX_UTF16},
  241.     {"utf16be",        IDX_UTF16},
  242.     {"utf-16be",    IDX_UTF16},
  243.     {"utf16le",        IDX_UTF16LE},
  244.     {"ucs4",        IDX_UCS4},
  245.     {"ucs4be",        IDX_UCS4},
  246.     {"ucs-4be",        IDX_UCS4},
  247.     {"ucs4le",        IDX_UCS4LE},
  248.     {"932",        IDX_CP932},
  249.     {"949",        IDX_CP949},
  250.     {"936",        IDX_CP936},
  251.     {"950",        IDX_CP950},
  252.     {"eucjp",        IDX_EUC_JP},
  253.     {"unix-jis",    IDX_EUC_JP},
  254.     {"ujis",        IDX_EUC_JP},
  255.     {"shift-jis",    IDX_SJIS},
  256.     {"euckr",        IDX_EUC_KR},
  257.     {"5601",        IDX_EUC_KR},    /* Sun: KS C 5601 */
  258.     {"euccn",        IDX_EUC_CN},
  259.     {"gb2312",        IDX_EUC_CN},
  260.     {"euctw",        IDX_EUC_TW},
  261. #if defined(WIN3264) || defined(WIN32UNIX) || defined(MACOS)
  262.     {"japan",        IDX_CP932},
  263.     {"korea",        IDX_CP949},
  264.     {"prc",        IDX_CP936},
  265.     {"chinese",        IDX_CP936},
  266.     {"taiwan",        IDX_CP950},
  267.     {"big5",        IDX_CP950},
  268. #else
  269.     {"japan",        IDX_EUC_JP},
  270.     {"korea",        IDX_EUC_KR},
  271.     {"prc",        IDX_EUC_CN},
  272.     {"chinese",        IDX_EUC_CN},
  273.     {"taiwan",        IDX_EUC_TW},
  274.     {"cp950",        IDX_BIG5},
  275.     {"950",        IDX_BIG5},
  276. #endif
  277.     {NULL,        0}
  278. };
  279.  
  280. /*
  281.  * Find encoding "name" in the list of canonical encoding names.
  282.  * Returns -1 if not found.
  283.  */
  284.     static int
  285. enc_canon_search(name)
  286.     char_u    *name;
  287. {
  288.     int        i;
  289.  
  290.     for (i = 0; i < IDX_COUNT; ++i)
  291.     if (STRCMP(name, enc_canon_table[i].name) == 0)
  292.         return i;
  293.     return -1;
  294. }
  295.  
  296. /*
  297.  * Find canonical encoding "name" in the list and return its properties.
  298.  * Returns 0 if not found.
  299.  */
  300.     int
  301. enc_canon_props(name)
  302.     char_u    *name;
  303. {
  304.     int        i;
  305.  
  306.     i = enc_canon_search(name);
  307.     if (i >= 0)
  308.     return enc_canon_table[i].prop;
  309. #ifdef WIN3264
  310.     if (name[0] == 'c' && name[1] == 'p' && isdigit(name[2]))
  311.     {
  312.     CPINFO    cpinfo;
  313.  
  314.     /* Get info on this codepage to find out what it is. */
  315.     if (GetCPInfo(atoi(name + 2), &cpinfo) != 0)
  316.     {
  317.         if (cpinfo.MaxCharSize == 1) /* some single-byte encoding */
  318.         return ENC_8BIT;
  319.         if (cpinfo.MaxCharSize == 2
  320.             && (cpinfo.LeadByte[0] != 0 || cpinfo.LeadByte[1] != 0))
  321.         /* must be a DBCS encoding */
  322.         return ENC_DBCS;
  323.     }
  324.     return 0;
  325.     }
  326. #endif
  327.     if (STRNCMP(name, "2byte-", 6) == 0)
  328.     return ENC_DBCS;
  329.     if (STRNCMP(name, "8bit-", 5) == 0 || STRNCMP(name, "iso-8859-", 9) == 0)
  330.     return ENC_8BIT;
  331.     return 0;
  332. }
  333.  
  334. /*
  335.  * Set up for using multi-byte characters.
  336.  * Called in three cases:
  337.  * - by main() to initialize (p_enc == NULL)
  338.  * - by set_init_1() after 'encoding' was set to its default.
  339.  * - by do_set() when 'encoding' has been set.
  340.  * p_enc must have been passed through enc_canonize() already.
  341.  * Sets the "enc_unicode", "enc_utf8", "enc_dbcs" and "has_mbyte" flags.
  342.  * Fills mb_bytelen_tab[] and returns NULL when there are no problems.
  343.  * When there is something wrong: Returns an error message and doesn't change
  344.  * anything.
  345.  */
  346.     char_u *
  347. mb_init()
  348. {
  349.     int        i;
  350.     int        idx;
  351.     int        n;
  352.     int        enc_dbcs_new = 0;
  353.  
  354.     if (p_enc == NULL)
  355.     {
  356.     /* Just starting up: set the whole table to one's. */
  357.     for (i = 0; i < 256; ++i)
  358.         mb_bytelen_tab[i] = 1;
  359.     input_conv.vc_type = CONV_NONE;
  360.     input_conv.vc_factor = 1;
  361.     output_conv.vc_type = CONV_NONE;
  362. #ifdef USE_ICONV
  363.     input_conv.vc_fd = (iconv_t)-1;
  364.     output_conv.vc_fd = (iconv_t)-1;
  365. #endif
  366.     return NULL;
  367.     }
  368.  
  369. #ifdef WIN3264
  370.     if (p_enc[0] == 'c' && p_enc[1] == 'p' && isdigit(p_enc[2]))
  371.     {
  372.     CPINFO    cpinfo;
  373.  
  374.     /* Get info on this codepage to find out what it is. */
  375.     if (GetCPInfo(atoi(p_enc + 2), &cpinfo) != 0)
  376.     {
  377.         if (cpinfo.MaxCharSize == 1)
  378.         {
  379.         /* some single-byte encoding */
  380.         enc_unicode = 0;
  381.         enc_utf8 = FALSE;
  382.         }
  383.         else if (cpinfo.MaxCharSize == 2
  384.             && (cpinfo.LeadByte[0] != 0 || cpinfo.LeadByte[1] != 0))
  385.         {
  386.         /* must be a DBCS encoding, check below */
  387.         enc_dbcs_new = atoi(p_enc + 2);
  388.         }
  389.         else
  390.         goto codepage_invalid;
  391.     }
  392.     else if (GetLastError() == ERROR_INVALID_PARAMETER)
  393.     {
  394. codepage_invalid:
  395.         return (char_u *)N_("Not a valid codepage");
  396.     }
  397.     }
  398. #endif
  399.     else if (STRNCMP(p_enc, "8bit-", 5) == 0
  400.         || STRNCMP(p_enc, "iso-8859-", 9) == 0)
  401.     {
  402.     /* Accept any "8bit-" or "iso-8859-" name. */
  403.     enc_unicode = 0;
  404.     enc_utf8 = FALSE;
  405.     }
  406.     else if (STRNCMP(p_enc, "2byte-", 6) == 0)
  407.     {
  408. #ifdef WIN3264
  409.     /* Windows: accept only valid codepage numbers, check below. */
  410.     if (p_enc[6] != 'c' || p_enc[7] != 'p'
  411.                       || (enc_dbcs_new = atoi(p_enc + 8)) == 0)
  412.         return e_invarg;
  413. #else
  414.     /* Unix: accept any "2byte-" name, assume current locale. */
  415.     enc_dbcs_new = DBCS_2BYTE;
  416. #endif
  417.     }
  418.     else if ((idx = enc_canon_search(p_enc)) >= 0)
  419.     {
  420.     i = enc_canon_table[idx].prop;
  421.     if (i & ENC_UNICODE)
  422.     {
  423.         /* Unicode */
  424.         enc_utf8 = TRUE;
  425.         if (i & (ENC_2BYTE | ENC_2WORD))
  426.         enc_unicode = 2;
  427.         else if (i & ENC_4BYTE)
  428.         enc_unicode = 4;
  429.         else
  430.         enc_unicode = 0;
  431.     }
  432.     else if (i & ENC_DBCS)
  433.     {
  434.         /* 2byte, handle below */
  435.         enc_dbcs_new = enc_canon_table[idx].codepage;
  436.     }
  437.     else
  438.     {
  439.         /* Must be 8-bit. */
  440.         enc_unicode = 0;
  441.         enc_utf8 = FALSE;
  442.     }
  443.     }
  444.     else    /* Don't know what encoding this is, reject it. */
  445.     return e_invarg;
  446.  
  447.     if (enc_dbcs_new != 0)
  448.     {
  449. #ifdef WIN3264
  450.     /* Check if the DBCS code page is OK. */
  451.     if (!IsValidCodePage(enc_dbcs_new))
  452.         goto codepage_invalid;
  453. #endif
  454.     enc_unicode = 0;
  455.     enc_utf8 = FALSE;
  456.     }
  457.     enc_dbcs = enc_dbcs_new;
  458.  
  459. #ifdef FEAT_GUI_W32
  460.     /* Check for codepage which is not the current one. */
  461.     is_funky_dbcs = (enc_dbcs != 0 && ((int)GetACP() != enc_dbcs));
  462. #endif
  463.  
  464.     has_mbyte = (enc_dbcs != 0 || enc_utf8);
  465.  
  466.     /*
  467.      * Set the function pointers.
  468.      */
  469.     if (enc_utf8)
  470.     {
  471.     mb_ptr2len_check = utfc_ptr2len_check;
  472.     mb_char2len = utf_char2len;
  473.     mb_char2bytes = utf_char2bytes;
  474.     mb_ptr2cells = utf_ptr2cells;
  475.     mb_char2cells = utf_char2cells;
  476.     mb_off2cells = utf_off2cells;
  477.     mb_ptr2char = utf_ptr2char;
  478.     mb_head_off = utf_head_off;
  479.     }
  480.     else if (enc_dbcs != 0)
  481.     {
  482.     mb_ptr2len_check = dbcs_ptr2len_check;
  483.     mb_char2len = dbcs_char2len;
  484.     mb_char2bytes = dbcs_char2bytes;
  485.     mb_ptr2cells = dbcs_ptr2cells;
  486.     mb_char2cells = dbcs_char2cells;
  487.     mb_off2cells = dbcs_off2cells;
  488.     mb_ptr2char = dbcs_ptr2char;
  489.     mb_head_off = dbcs_head_off;
  490.     }
  491.     else
  492.     {
  493.     mb_ptr2len_check = latin_ptr2len_check;
  494.     mb_char2len = latin_char2len;
  495.     mb_char2bytes = latin_char2bytes;
  496.     mb_ptr2cells = latin_ptr2cells;
  497.     mb_char2cells = latin_char2cells;
  498.     mb_off2cells = latin_off2cells;
  499.     mb_ptr2char = latin_ptr2char;
  500.     mb_head_off = latin_head_off;
  501.     }
  502.  
  503.     /*
  504.      * Fill the mb_bytelen_tab[] for MB_BYTE2LEN().
  505.      */
  506.     for (i = 0; i < 256; ++i)
  507.     {
  508.     /* Our own function to reliably check the lenght of UTF-8 characters,
  509.      * independent of mblen(). */
  510.     if (enc_utf8)
  511.         n = utf8len_tab[i];
  512.     else if (enc_dbcs == 0)
  513.         n = 1;
  514.     else
  515.     {
  516. #if defined(WIN3264) || defined(WIN32UNIX)
  517.         /* enc_dbcs is set by setting 'fileencoding'.  It becomes a Windows
  518.          * CodePage identifier, which we can pass directly in to Windows
  519.          * API */
  520.         n = IsDBCSLeadByteEx(enc_dbcs, (BYTE)i) ? 2 : 1;
  521. #else
  522. # ifdef MACOS
  523.         /*
  524.          * if mblen() is not available, character which MSB is turned on
  525.          * are treated as leading byte character. (note : This assumption
  526.          * is not always true.)
  527.          */
  528.         n = (i & 0x80) ? 2 : 1;
  529. # else
  530.         char buf[MB_MAXBYTES];
  531. # ifdef X_LOCALE
  532.         extern int _Xmblen __ARGS((char *, size_t));
  533. #  ifndef mblen
  534. #   define mblen _Xmblen
  535. #  endif
  536. # endif
  537.         if (i == NUL)    /* just in case mblen() can't handle "" */
  538.         n = 1;
  539.         else
  540.         {
  541.         /*
  542.          * mblen() should return -1 for invalid (means the leading
  543.          * multibyte) character.  However there are some platform
  544.          * where mblen() returns 0 for invalid character.  Therefore,
  545.          * following condition includes 0.
  546.          */
  547.         buf[0] = i;
  548.         buf[1] = 0;
  549. #if 0
  550.         if (i >= 0x80)/* TESTING DBCS: 'encoding' != current locale */
  551. #else
  552.         if (mblen(buf, (size_t)1) <= 0)
  553. #endif
  554.             n = 2;
  555.         else
  556.             n = 1;
  557.         }
  558. # endif
  559. #endif
  560.     }
  561.  
  562.     mb_bytelen_tab[i] = n;
  563.     }
  564.  
  565.     /* The cell width depends on the type of multi-byte characters. */
  566.     (void)init_chartab();
  567.  
  568.     /* When enc_utf8 is set or reset, (de)allocate ScreenLinesUC[] */
  569.     screenalloc(FALSE);
  570.  
  571.     /* When using Unicode, set default for 'fileencodings'. */
  572.     if (enc_utf8 && !option_was_set((char_u *)"fencs"))
  573.     set_string_option_direct((char_u *)"fencs", -1,
  574.                  (char_u *)"ucs-bom,utf-8,latin1", OPT_FREE);
  575.  
  576. #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  577.     /* GNU gettext 0.10.37 supports this feature: set the codeset used for
  578.      * translated messages independently from the current locale. */
  579.     (void)bind_textdomain_codeset(VIMPACKAGE,
  580.                       enc_utf8 ? "utf-8" : (char *)p_enc);
  581. #endif
  582.  
  583. #ifdef FEAT_AUTOCMD
  584.     /* Fire an autocommand to let people do custom font setup. This must be
  585.      * after Vim has been setup for the new encoding. */
  586.     apply_autocmds(EVENT_ENCODINGCHANGED, NULL, (char_u *)"", FALSE, curbuf);
  587. #endif
  588.  
  589.     return NULL;
  590. }
  591.  
  592. /*
  593.  * Return the size of the BOM for the current buffer:
  594.  * 0 - no BOM
  595.  * 2 - UCS-2 or UTF-16 BOM
  596.  * 4 - UCS-4 BOM
  597.  * 3 - UTF-8 BOM
  598.  */
  599.     int
  600. bomb_size()
  601. {
  602.     int n = 0;
  603.  
  604.     if (curbuf->b_p_bomb && !curbuf->b_p_bin)
  605.     {
  606.     if (*curbuf->b_p_fenc == NUL)
  607.     {
  608.         if (enc_utf8)
  609.         {
  610.         if (enc_unicode != 0)
  611.             n = enc_unicode;
  612.         else
  613.             n = 3;
  614.         }
  615.     }
  616.     else if (STRCMP(curbuf->b_p_fenc, "utf-8") == 0)
  617.         n = 3;
  618.     else if (STRNCMP(curbuf->b_p_fenc, "ucs-2", 5) == 0
  619.         || STRNCMP(curbuf->b_p_fenc, "utf-16", 6) == 0)
  620.         n = 2;
  621.     else if (STRNCMP(curbuf->b_p_fenc, "ucs-4", 5) == 0)
  622.         n = 4;
  623.     }
  624.     return n;
  625. }
  626.  
  627. /*
  628.  * Get class of pointer:
  629.  * 0 for blank or NUL
  630.  * 1 for punctuation
  631.  * 2 for an (ASCII) word character
  632.  * >2 for other word characters
  633.  */
  634.     int
  635. mb_get_class(p)
  636.     char_u    *p;
  637. {
  638.     if (MB_BYTE2LEN(p[0]) == 1)
  639.     {
  640.     if (p[0] == NUL || vim_iswhite(p[0]))
  641.         return 0;
  642.     if (vim_iswordc(p[0]))
  643.         return 2;
  644.     return 1;
  645.     }
  646.     if (enc_dbcs != 0 && p[0] != NUL && p[1] != NUL)
  647.     return dbcs_class(p[0], p[1]);
  648.     if (enc_utf8)
  649.     return utf_class(utf_ptr2char(p));
  650.     return 0;
  651. }
  652.  
  653. /*
  654.  * Get class of a double-byte character.  This always returns 3 or bigger.
  655.  * TODO: Should return 1 for punctuation.
  656.  */
  657.     int
  658. dbcs_class(lead, trail)
  659.     unsigned    lead;
  660.     unsigned    trail;
  661. {
  662.     switch (enc_dbcs)
  663.     {
  664.     /* please add classfy routine for your language in here */
  665.  
  666.     case DBCS_JPNU:    /* ? */
  667.     case DBCS_JPN:
  668.         {
  669.         /* JIS code classification */
  670.         unsigned char lb = lead;
  671.         unsigned char tb = trail;
  672.  
  673.         /* convert process code to JIS */
  674. # if defined(WIN3264) || defined(WIN32UNIX) || defined(MACOS)
  675.         /* process code is SJIS */
  676.         if (lb <= 0x9f)
  677.             lb = (lb - 0x81) * 2 + 0x21;
  678.         else
  679.             lb = (lb - 0xc1) * 2 + 0x21;
  680.         if (tb <= 0x7e)
  681.             tb -= 0x1f;
  682.         else if (tb <= 0x9e)
  683.             tb -= 0x20;
  684.         else
  685.         {
  686.             tb -= 0x7e;
  687.             lb += 1;
  688.         }
  689. # else
  690.         /*
  691.          * XXX: Code page identification can not use with all
  692.          *        system! So, some other encoding information
  693.          *        will be needed.
  694.          *        In japanese: SJIS,EUC,UNICODE,(JIS)
  695.          *        Note that JIS-code system don't use as
  696.          *        process code in most system because it uses
  697.          *        escape sequences(JIS is context depend encoding).
  698.          */
  699.         /* assume process code is JAPANESE-EUC */
  700.         lb &= 0x7f;
  701.         tb &= 0x7f;
  702. # endif
  703.         /* exceptions */
  704.         switch (lb << 8 | tb)
  705.         {
  706.             case 0x2121: /* ZENKAKU space */
  707.             return 0;
  708.             case 0x2122: /* KU-TEN (Japanese comma) */
  709.             case 0x2123: /* TOU-TEN (Japanese period) */
  710.             case 0x2124: /* ZENKAKU comma */
  711.             case 0x2125: /* ZENKAKU period */
  712.             return 1;
  713.             case 0x213c: /* prolongedsound handled as KATAKANA */
  714.             return 13;
  715.         }
  716.         /* sieved by KU code */
  717.         switch (lb)
  718.         {
  719.             case 0x21:
  720.             case 0x22:
  721.             /* special symbols */
  722.             return 10;
  723.             case 0x23:
  724.             /* alpha-numeric */
  725.             return 11;
  726.             case 0x24:
  727.             /* hiragana */
  728.             return 12;
  729.             case 0x25:
  730.             /* katakana */
  731.             return 13;
  732.             case 0x26:
  733.             /* greek */
  734.             return 14;
  735.             case 0x27:
  736.             /* russian */
  737.             return 15;
  738.             case 0x28:
  739.             /* lines */
  740.             return 16;
  741.             default:
  742.             /* kanji */
  743.             return 17;
  744.         }
  745.         }
  746.  
  747.     case DBCS_KORU:    /* ? */
  748.     case DBCS_KOR:
  749.         {
  750.         /* KS code classification */
  751.         unsigned char c1 = lead;
  752.         unsigned char c2 = trail;
  753.  
  754.         /*
  755.          * 20 : Hangul
  756.          * 21 : Hanja
  757.          * 22 : Symbols
  758.          * 23 : Alpha-numeric/Roman Letter (Full width)
  759.          * 24 : Hangul Letter(Alphabet)
  760.          * 25 : Roman Numeral/Greek Letter
  761.          * 26 : Box Drawings
  762.          * 27 : Unit Symbols
  763.          * 28 : Circled/Parenthesized Letter
  764.          * 29 : Hirigana/Katakana
  765.          * 30 : Cyrillic Letter
  766.          */
  767.  
  768.         if (c1 >= 0xB0 && c1 <= 0xC8)
  769.             /* Hangul */
  770.             return 20;
  771. #if defined(WIN3264) || defined(WIN32UNIX)
  772.         else if (c1 <= 0xA0 || c2 <= 0xA0)
  773.             /* Extended Hangul Region : MS UHC(Unified Hangul Code) */
  774.             /* c1: 0x81-0xA0 with c2: 0x41-0x5A, 0x61-0x7A, 0x81-0xFE
  775.              * c1: 0xA1-0xC6 with c2: 0x41-0x5A, 0x61-0x7A, 0x81-0xA0
  776.              */
  777.             return 20;
  778. #endif
  779.  
  780.         else if (c1 >= 0xCA && c1 <= 0xFD)
  781.             /* Hanja */
  782.             return 21;
  783.         else switch (c1)
  784.         {
  785.             case 0xA1:
  786.             case 0xA2:
  787.             /* Symbols */
  788.             return 22;
  789.             case 0xA3:
  790.             /* Alpha-numeric */
  791.             return 23;
  792.             case 0xA4:
  793.             /* Hangul Letter(Alphabet) */
  794.             return 24;
  795.             case 0xA5:
  796.             /* Roman Numeral/Greek Letter */
  797.             return 25;
  798.             case 0xA6:
  799.             /* Box Drawings */
  800.             return 26;
  801.             case 0xA7:
  802.             /* Unit Symbols */
  803.             return 27;
  804.             case 0xA8:
  805.             case 0xA9:
  806.             if (c2 <= 0xAF)
  807.                 return 25;  /* Roman Letter */
  808.             else if (c2 >= 0xF6)
  809.                 return 22;  /* Symbols */
  810.             else
  811.                 /* Circled/Parenthesized Letter */
  812.                 return 28;
  813.             case 0xAA:
  814.             case 0xAB:
  815.             /* Hirigana/Katakana */
  816.             return 29;
  817.             case 0xAC:
  818.             /* Cyrillic Letter */
  819.             return 30;
  820.         }
  821.         }
  822.     default:
  823.         break;
  824.     }
  825.     return 3;
  826. }
  827.  
  828. /*
  829.  * mb_char2len() function pointer.
  830.  * Return length in bytes of character "c".
  831.  * Returns 1 for a single-byte character.
  832.  */
  833. /* ARGSUSED */
  834.     int
  835. latin_char2len(c)
  836.     int        c;
  837. {
  838.     return 1;
  839. }
  840.  
  841.     static int
  842. dbcs_char2len(c)
  843.     int        c;
  844. {
  845.     if (c >= 0x100)
  846.     return 2;
  847.     return 1;
  848. }
  849.  
  850. /*
  851.  * mb_char2bytes() function pointer.
  852.  * Convert a character to its bytes.
  853.  * Returns the length in bytes.
  854.  */
  855.     int
  856. latin_char2bytes(c, buf)
  857.     int        c;
  858.     char_u    *buf;
  859. {
  860.     buf[0] = c;
  861.     return 1;
  862. }
  863.  
  864.     static int
  865. dbcs_char2bytes(c, buf)
  866.     int        c;
  867.     char_u    *buf;
  868. {
  869.     if (c >= 0x100)
  870.     {
  871.     buf[0] = (unsigned)c >> 8;
  872.     buf[1] = c;
  873.     return 2;
  874.     }
  875.     buf[0] = c;
  876.     return 1;
  877. }
  878.  
  879. /*
  880.  * mb_ptr2len_check() function pointer.
  881.  * Get byte length of character at "*p" but stop at a NUL.
  882.  * For UTF-8 this includes following composing characters.
  883.  * Returns 0 when *p is NUL.
  884.  *
  885.  */
  886.     int
  887. latin_ptr2len_check(p)
  888.     char_u    *p;
  889. {
  890.     return MB_BYTE2LEN(*p);
  891. }
  892.  
  893.     static int
  894. dbcs_ptr2len_check(p)
  895.     char_u    *p;
  896. {
  897.     int        len;
  898.  
  899.     /* Check if second byte is not missing. */
  900.     len = MB_BYTE2LEN(*p);
  901.     if (len == 2 && p[1] == NUL)
  902.     len = 1;
  903.     return len;
  904. }
  905.  
  906. /*
  907.  * For UTF-8 character "c" return 2 for a double-width character, 1 for others.
  908.  */
  909.     int
  910. utf_char2cells(c)
  911.     int        c;
  912. {
  913.     if (c <= 0x9f && c >= 0x80)        /* unprintable, displays <xx> */
  914.     return 4;
  915.     if (c >= 0x100 && !utf_printable(c))
  916.     return 6;            /* unprintable, displays <xxxx> */
  917.     if (c >= 0x1100
  918.         && (c <= 0x115f            /* Hangul Jamo */
  919.         || (c >= 0x2e80 && c <= 0xa4cf && (c & ~0x0011) != 0x300a
  920.             && c != 0x303f)        /* CJK ... Yi */
  921.         || (c >= 0xac00 && c <= 0xd7a3)    /* Hangul Syllables */
  922.         || (c >= 0xf900 && c <= 0xfaff)    /* CJK Compatibility
  923.                            Ideographs */
  924.         || (c >= 0xfe30 && c <= 0xfe6f)    /* CJK Compatibility Forms */
  925.         || (c >= 0xff00 && c <= 0xff5f)    /* Fullwidth Forms */
  926.         || (c >= 0xffe0 && c <= 0xffe6)
  927.         || (c >= 0x20000 && c <= 0x2ffff)))
  928.     return 2;
  929.     return 1;
  930. }
  931.  
  932. /*
  933.  * mb_ptr2cells() function pointer.
  934.  * Return the number of display cells character at "*p" occupies.
  935.  * This doesn't take care of unprintable characters, use ptr2cells() for that.
  936.  */
  937. /*ARGSUSED*/
  938.     int
  939. latin_ptr2cells(p)
  940.     char_u    *p;
  941. {
  942.     return 1;
  943. }
  944.  
  945.     int
  946. utf_ptr2cells(p)
  947.     char_u    *p;
  948. {
  949.     int        c;
  950.  
  951.     /* Need to convert to a wide character. */
  952.     if (*p >= 0x80)
  953.     {
  954.     c = utf_ptr2char(p);
  955.     /* An illegal byte is displayed as <xx>. */
  956.     if (utf_ptr2len_check(p) == 1 || c == NUL)
  957.         return 4;
  958.     /* If the char is ASCII it must be an overlong sequence. */
  959.     if (c < 0x80)
  960.         return char2cells(c);
  961.     return utf_char2cells(c);
  962.     }
  963.     return 1;
  964. }
  965.  
  966.     int
  967. dbcs_ptr2cells(p)
  968.     char_u    *p;
  969. {
  970.     /* Number of cells is equal to number of bytes, except for euc-jp when
  971.      * the first byte is 0x8e. */
  972.     if (enc_dbcs == DBCS_JPNU && *p == 0x8e)
  973.     return 1;
  974.     return MB_BYTE2LEN(*p);
  975. }
  976.  
  977. /*
  978.  * mb_char2cells() function pointer.
  979.  * Return the number of display cells character "c" occupies.
  980.  * Only takes care of multi-byte chars, not "^C" and such.
  981.  */
  982. /*ARGSUSED*/
  983.     int
  984. latin_char2cells(c)
  985.     int        c;
  986. {
  987.     return 1;
  988. }
  989.  
  990.     static int
  991. dbcs_char2cells(c)
  992.     int        c;
  993. {
  994.     /* Number of cells is equal to number of bytes, except for euc-jp when
  995.      * the first byte is 0x8e. */
  996.     if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
  997.     return 1;
  998.     /* use the first byte */
  999.     return MB_BYTE2LEN((unsigned)c >> 8);
  1000. }
  1001.  
  1002. /*
  1003.  * mb_off2cells() function pointer.
  1004.  * Return number of display cells for char at ScreenLines[off].
  1005.  * Caller must make sure "off" and "off + 1" are valid!
  1006.  */
  1007. /*ARGSUSED*/
  1008.     int
  1009. latin_off2cells(off)
  1010.     unsigned    off;
  1011. {
  1012.     return 1;
  1013. }
  1014.  
  1015.     int
  1016. dbcs_off2cells(off)
  1017.     unsigned    off;
  1018. {
  1019.     /* Number of cells is equal to number of bytes, except for euc-jp when
  1020.      * the first byte is 0x8e. */
  1021.     if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
  1022.     return 1;
  1023.     return MB_BYTE2LEN(ScreenLines[off]);
  1024. }
  1025.  
  1026.     int
  1027. utf_off2cells(off)
  1028.     unsigned    off;
  1029. {
  1030.     return ScreenLines[off + 1] == 0 ? 2 : 1;
  1031. }
  1032.  
  1033. /*
  1034.  * mb_ptr2char() function pointer.
  1035.  * Convert a byte sequence into a character.
  1036.  */
  1037.     int
  1038. latin_ptr2char(p)
  1039.     char_u    *p;
  1040. {
  1041.     return *p;
  1042. }
  1043.  
  1044.     static int
  1045. dbcs_ptr2char(p)
  1046.     char_u    *p;
  1047. {
  1048.     if (MB_BYTE2LEN(*p) > 1 && p[1] != NUL)
  1049.     return (p[0] << 8) + p[1];
  1050.     return *p;
  1051. }
  1052.  
  1053. /*
  1054.  * Convert a UTF-8 byte sequence to a wide character.
  1055.  * If the sequence is illegal or truncated by a NUL the first byte is
  1056.  * returned.
  1057.  * Does not include composing characters, of course.
  1058.  */
  1059.     int
  1060. utf_ptr2char(p)
  1061.     char_u    *p;
  1062. {
  1063.     int        len;
  1064.  
  1065.     if (p[0] < 0x80)    /* be quick for ASCII */
  1066.     return p[0];
  1067.  
  1068.     len = utf8len_tab[p[0]];
  1069.     if ((p[1] & 0xc0) == 0x80)
  1070.     {
  1071.     if (len == 2)
  1072.         return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
  1073.     if ((p[2] & 0xc0) == 0x80)
  1074.     {
  1075.         if (len == 3)
  1076.         return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
  1077.             + (p[2] & 0x3f);
  1078.         if ((p[3] & 0xc0) == 0x80)
  1079.         {
  1080.         if (len == 4)
  1081.             return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
  1082.             + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f);
  1083.         if ((p[4] & 0xc0) == 0x80)
  1084.         {
  1085.             if (len == 5)
  1086.             return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
  1087.                 + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
  1088.                 + (p[4] & 0x3f);
  1089.             if ((p[5] & 0xc0) == 0x80 && len == 6)
  1090.             return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
  1091.                 + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
  1092.                 + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f);
  1093.         }
  1094.         }
  1095.     }
  1096.     }
  1097.     /* Illegal value, just return the first byte */
  1098.     return p[0];
  1099. }
  1100.  
  1101. /*
  1102.  * Get character at **pp and advance *pp to the next character.
  1103.  * Note: composing characters are skipped!
  1104.  */
  1105.     int
  1106. mb_ptr2char_adv(pp)
  1107.     char_u    **pp;
  1108. {
  1109.     int        c;
  1110.  
  1111.     c = (*mb_ptr2char)(*pp);
  1112.     *pp += (*mb_ptr2len_check)(*pp);
  1113.     return c;
  1114. }
  1115.  
  1116. /*
  1117.  * Convert a UTF-8 byte string to a wide chararacter.  Also get up to two
  1118.  * composing characters.
  1119.  */
  1120.     int
  1121. utfc_ptr2char(p, p1, p2)
  1122.     char_u    *p;
  1123.     int        *p1;    /* return: first composing char or 0 */
  1124.     int        *p2;    /* return: second composing char or 0 */
  1125. {
  1126.     int        len;
  1127.     int        c;
  1128.     int        cc;
  1129.  
  1130.     c = utf_ptr2char(p);
  1131.     len = utf_ptr2len_check(p);
  1132.     /* Only accept a composing char when the first char isn't illegal. */
  1133.     if ((len > 1 || *p < 0x80)
  1134.         && p[len] >= 0x80 && utf_iscomposing(cc = utf_ptr2char(p + len)))
  1135.     {
  1136.     *p1 = cc;
  1137.     len += utf_ptr2len_check(p + len);
  1138.     if (p[len] >= 0x80 && utf_iscomposing(cc = utf_ptr2char(p + len)))
  1139.         *p2 = cc;
  1140.     else
  1141.         *p2 = 0;
  1142.     }
  1143.     else
  1144.     {
  1145.     *p1 = 0;
  1146.     *p2 = 0;
  1147.     }
  1148.     return c;
  1149. }
  1150.  
  1151. /*
  1152.  * Convert the character at screen position "off" to a sequence of bytes.
  1153.  * Includes the composing characters.
  1154.  * "buf" must at least have the length MB_MAXBYTES.
  1155.  * Returns the produced number of bytes.
  1156.  */
  1157.     int
  1158. utfc_char2bytes(off, buf)
  1159.     int        off;
  1160.     char_u    *buf;
  1161. {
  1162.     int        len;
  1163.  
  1164.     len = utf_char2bytes(ScreenLinesUC[off], buf);
  1165.     if (ScreenLinesC1[off] != 0)
  1166.     {
  1167.     len += utf_char2bytes(ScreenLinesC1[off], buf + len);
  1168.     if (ScreenLinesC2[off] != 0)
  1169.         len += utf_char2bytes(ScreenLinesC2[off], buf + len);
  1170.     }
  1171.     return len;
  1172. }
  1173.  
  1174. /*
  1175.  * Get the length of a UTF-8 byte sequence.  Ignores any following composing
  1176.  * characters.
  1177.  * Returns 0 for "".
  1178.  * Returns 1 for an illegal byte sequence.
  1179.  */
  1180.     int
  1181. utf_ptr2len_check(p)
  1182.     char_u    *p;
  1183. {
  1184.     int        len;
  1185.     int        i;
  1186.  
  1187.     if (*p == NUL)
  1188.     return 0;
  1189.     len = utf8len_tab[*p];
  1190.     for (i = 1; i < len; ++i)
  1191.     if ((p[i] & 0xc0) != 0x80)
  1192.         return 1;
  1193.     return len;
  1194. }
  1195.  
  1196. /*
  1197.  * Return length of UTF-8 character, obtained from the first byte.
  1198.  * "b" must be between 0 and 255!
  1199.  */
  1200.     int
  1201. utf_byte2len(b)
  1202.     int        b;
  1203. {
  1204.     return utf8len_tab[b];
  1205. }
  1206.  
  1207. /*
  1208.  * Get the length of UTF-8 byte sequence "p[size]".  Ignores any following
  1209.  * composing characters.
  1210.  * Returns 1 for "".
  1211.  * Returns 1 for an illegal byte sequence.
  1212.  * Returns number > "size" for an incomplete byte sequence.
  1213.  */
  1214.     int
  1215. utf_ptr2len_check_len(p, size)
  1216.     char_u    *p;
  1217.     int        size;
  1218. {
  1219.     int        len;
  1220.     int        i;
  1221.  
  1222.     if (*p == NUL)
  1223.     return 1;
  1224.     len = utf8len_tab[*p];
  1225.     for (i = 1; i < len && i < size; ++i)
  1226.     if ((p[i] & 0xc0) != 0x80)
  1227.         return 1;
  1228.     return len;
  1229. }
  1230.  
  1231. /*
  1232.  * Return the number of bytes the UTF-8 encoding of the character at "p" takes.
  1233.  * This includes following composing characters.
  1234.  */
  1235.     int
  1236. utfc_ptr2len_check(p)
  1237.     char_u    *p;
  1238. {
  1239.     int        len;
  1240.  
  1241.     if (*p == NUL)
  1242.     return 0;
  1243.     if (p[0] < 0x80 && p[1] < 0x80)    /* be quick for ASCII */
  1244.     return 1;
  1245.  
  1246.     /* Skip over first UTF-8 char, stopping at a NUL byte. */
  1247.     len = utf_ptr2len_check(p);
  1248.  
  1249.     /* Check for illegal byte. */
  1250.     if (len == 1 && p[0] >= 0x80)
  1251.     return 1;
  1252.  
  1253.     /*
  1254.      * Check for composing characters.  We can handle only the first two, but
  1255.      * skip all of them (otherwise the cursor would get stuck).
  1256.      */
  1257.     for (;;)
  1258.     {
  1259.     if (p[len] < 0x80 || !utf_iscomposing(utf_ptr2char(p + len)))
  1260.         return len;
  1261.  
  1262.     /* Skip over composing char */
  1263.     len += utf_ptr2len_check(p + len);
  1264.     }
  1265. }
  1266.  
  1267. /*
  1268.  * Return the number of bytes the UTF-8 encoding of character "c" takes.
  1269.  * This does not include composing characters.
  1270.  */
  1271.     int
  1272. utf_char2len(c)
  1273.     int        c;
  1274. {
  1275.     if (c < 0x80)
  1276.     return 1;
  1277.     if (c < 0x800)
  1278.     return 2;
  1279.     if (c < 0x10000)
  1280.     return 3;
  1281.     if (c < 0x200000)
  1282.     return 4;
  1283.     if (c < 0x4000000)
  1284.     return 5;
  1285.     return 6;
  1286. }
  1287.  
  1288. /*
  1289.  * Convert UTF-8 character "c" to string of bytes in "buf[]".
  1290.  * Returns the number of bytes.
  1291.  * This does not include composing characters.
  1292.  */
  1293.     int
  1294. utf_char2bytes(c, buf)
  1295.     int        c;
  1296.     char_u    *buf;
  1297. {
  1298.     if (c < 0x80)        /* 7 bits */
  1299.     {
  1300.     buf[0] = c;
  1301.     return 1;
  1302.     }
  1303.     if (c < 0x800)        /* 11 bits */
  1304.     {
  1305.     buf[0] = 0xc0 + ((unsigned)c >> 6);
  1306.     buf[1] = 0x80 + (c & 0x3f);
  1307.     return 2;
  1308.     }
  1309.     if (c < 0x10000)        /* 16 bits */
  1310.     {
  1311.     buf[0] = 0xe0 + ((unsigned)c >> 12);
  1312.     buf[1] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  1313.     buf[2] = 0x80 + (c & 0x3f);
  1314.     return 3;
  1315.     }
  1316.     if (c < 0x200000)        /* 21 bits */
  1317.     {
  1318.     buf[0] = 0xf0 + ((unsigned)c >> 18);
  1319.     buf[1] = 0x80 + (((unsigned)c >> 12) & 0x3f);
  1320.     buf[2] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  1321.     buf[3] = 0x80 + (c & 0x3f);
  1322.     return 4;
  1323.     }
  1324.     if (c < 0x4000000)        /* 26 bits */
  1325.     {
  1326.     buf[0] = 0xf8 + ((unsigned)c >> 24);
  1327.     buf[1] = 0x80 + (((unsigned)c >> 18) & 0x3f);
  1328.     buf[2] = 0x80 + (((unsigned)c >> 12) & 0x3f);
  1329.     buf[3] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  1330.     buf[4] = 0x80 + (c & 0x3f);
  1331.     return 5;
  1332.     }
  1333.                 /* 31 bits */
  1334.     buf[0] = 0xfc + ((unsigned)c >> 30);
  1335.     buf[1] = 0x80 + (((unsigned)c >> 24) & 0x3f);
  1336.     buf[2] = 0x80 + (((unsigned)c >> 18) & 0x3f);
  1337.     buf[3] = 0x80 + (((unsigned)c >> 12) & 0x3f);
  1338.     buf[4] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  1339.     buf[5] = 0x80 + (c & 0x3f);
  1340.     return 6;
  1341. }
  1342.  
  1343. struct interval
  1344. {
  1345.     unsigned short first;
  1346.     unsigned short last;
  1347. };
  1348. static int intable __ARGS((struct interval *table, int size, int c));
  1349.  
  1350. /*
  1351.  * Return TRUE if "c" is in "table[size]".
  1352.  */
  1353.     static int
  1354. intable(table, size, c)
  1355.     struct interval    *table;
  1356.     int            size;
  1357.     int            c;
  1358. {
  1359.     int mid, bot, top;
  1360.  
  1361.     /* first quick check for Latin1 etc. characters */
  1362.     if (c < table[0].first)
  1363.     return FALSE;
  1364.  
  1365.     /* binary search in table */
  1366.     bot = 0;
  1367.     top = size - 1;
  1368.     while (top >= bot)
  1369.     {
  1370.     mid = (bot + top) / 2;
  1371.     if (table[mid].last < c)
  1372.         bot = mid + 1;
  1373.     else if (table[mid].first > c)
  1374.         top = mid - 1;
  1375.     else
  1376.         return TRUE;
  1377.     }
  1378.     return FALSE;
  1379. }
  1380.  
  1381. /*
  1382.  * Return TRUE if "c" is a composing UTF-8 character.  This means it will be
  1383.  * drawn on top of the preceding character.
  1384.  * Based on code from Markus Kuhn.
  1385.  */
  1386.     int
  1387. utf_iscomposing(c)
  1388.     int        c;
  1389. {
  1390.     /* sorted list of non-overlapping intervals */
  1391.     static struct interval combining[] =
  1392.     {
  1393.     {0x0300, 0x034E}, {0x0360, 0x0362}, {0x0483, 0x0486}, {0x0488, 0x0489},
  1394.     {0x0591, 0x05A1}, {0x05A3, 0x05B9}, {0x05BB, 0x05BD}, {0x05BF, 0x05BF},
  1395.     {0x05C1, 0x05C2}, {0x05C4, 0x05C4}, {0x064B, 0x0655}, {0x0670, 0x0670},
  1396.     {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711},
  1397.     {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x0901, 0x0902}, {0x093C, 0x093C},
  1398.     {0x0941, 0x0948}, {0x094D, 0x094D}, {0x0951, 0x0954}, {0x0962, 0x0963},
  1399.     {0x0981, 0x0981}, {0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD},
  1400.     {0x09E2, 0x09E3}, {0x0A02, 0x0A02}, {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42},
  1401.     {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A70, 0x0A71}, {0x0A81, 0x0A82},
  1402.     {0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD},
  1403.     {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43},
  1404.     {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
  1405.     {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D},
  1406.     {0x0C55, 0x0C56}, {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
  1407.     {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4},
  1408.     {0x0DD6, 0x0DD6}, {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
  1409.     {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, {0x0EC8, 0x0ECD},
  1410.     {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37}, {0x0F39, 0x0F39},
  1411.     {0x0F71, 0x0F7E}, {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97},
  1412.     {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, {0x1032, 0x1032},
  1413.     {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059}, {0x17B7, 0x17BD},
  1414.     {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x18A9, 0x18A9}, {0x20D0, 0x20E3},
  1415.     {0x302A, 0x302F}, {0x3099, 0x309A}, {0xFB1E, 0xFB1E}, {0xFE20, 0xFE23}
  1416.     };
  1417.  
  1418.     return intable(combining, sizeof(combining) / sizeof(struct interval), c);
  1419. }
  1420.  
  1421. /*
  1422.  * Return TRUE for characters that can be displayed in a normal way.
  1423.  * Only for characters of 0x100 and above!
  1424.  */
  1425.     int
  1426. utf_printable(c)
  1427.     int        c;
  1428. {
  1429.     /* sorted list of non-overlapping intervals */
  1430.     static struct interval nonprint[] =
  1431.     {
  1432.     {0x070f, 0x070f}, {0x180b, 0x180e}, {0x200b, 0x200f}, {0x202a, 0x202e},
  1433.     {0x206a, 0x206f}, {0xfeff, 0xfeff}, {0xfff9, 0xfffb}
  1434.     };
  1435.  
  1436.     return !intable(nonprint, sizeof(nonprint) / sizeof(struct interval), c);
  1437. }
  1438.  
  1439. /*
  1440.  * Get class of a Unicode character.
  1441.  * 0: white space
  1442.  * 1: punctuation
  1443.  * 2 or bigger: some class of word character.
  1444.  */
  1445.     int
  1446. utf_class(c)
  1447.     int        c;
  1448. {
  1449.     /* sorted list of non-overlapping intervals */
  1450.     static struct interval
  1451.     {
  1452.     unsigned short first;
  1453.     unsigned short last;
  1454.     unsigned short class;
  1455.     } classes[] =
  1456.     {
  1457.     {0x037e, 0x037e, 1},        /* Greek question mark */
  1458.     {0x0387, 0x0387, 1},        /* Greek ano teleia */
  1459.     {0x055a, 0x055f, 1},        /* Armenian punctuation */
  1460.     {0x0589, 0x0589, 1},        /* Armenian full stop */
  1461.     {0x0700, 0x070d, 1},        /* Syriac punctuation */
  1462.     {0x104a, 0x104f, 1},        /* Myanmar punctuation */
  1463.     {0x10fb, 0x10fb, 1},        /* Georgian punctuation */
  1464.     {0x1361, 0x1368, 1},        /* Ethiopic punctuation */
  1465.     {0x166d, 0x166e, 1},        /* Canadian Syl. punctuation */
  1466.     {0x17d4, 0x17dc, 1},        /* Khmer punctuation */
  1467.     {0x1800, 0x180a, 1},        /* Mongolian punctuation */
  1468.     {0x2000, 0x200a, 0},        /* spaces */
  1469.     {0x200b, 0x27ff, 1},        /* punctuation and symbols */
  1470.     {0x2070, 0x207f, 0x2070},    /* superscript */
  1471.     {0x2080, 0x208f, 0x2080},    /* subscript */
  1472.     {0x3000, 0x3000, 0},        /* ideographic space */
  1473.     {0x3001, 0x3020, 1},        /* ideographic punctuation */
  1474.     {0x3040, 0x309f, 0x3040},    /* Hiragana */
  1475.     {0x30a0, 0x30ff, 0x30a0},    /* Katakana */
  1476.     {0x3300, 0x9fff, 0x4e00},    /* CJK Ideographs */
  1477.     {0xac00, 0xd7a3, 0xac00},    /* Hangul Syllables */
  1478.     {0xf900, 0xfaff, 0x4e00},    /* CJK Ideographs */
  1479.     {0xfe30, 0xfe6b, 1},        /* punctuation forms */
  1480.     {0xff00, 0xff0f, 1},        /* half/fullwidth ASCII */
  1481.     {0xff1a, 0xff20, 1},        /* half/fullwidth ASCII */
  1482.     {0xff3b, 0xff40, 1},        /* half/fullwidth ASCII */
  1483.     {0xff5b, 0xff64, 1},        /* half/fullwidth ASCII */
  1484.     };
  1485.     int bot = 0;
  1486.     int top = sizeof(classes) / sizeof(struct interval) - 1;
  1487.     int mid;
  1488.  
  1489.     /* First quick check for Latin1 characters, use 'iskeyword'. */
  1490.     if (c < 0x100)
  1491.     {
  1492.     if (c == ' ' || c == '\t' || c == NUL)
  1493.         return 0;        /* blank */
  1494.     if (vim_iswordc(c))
  1495.         return 2;        /* word character */
  1496.     return 1;        /* punctuation */
  1497.     }
  1498.  
  1499.     /* binary search in table */
  1500.     while (top >= bot)
  1501.     {
  1502.     mid = (bot + top) / 2;
  1503.     if (classes[mid].last < c)
  1504.         bot = mid + 1;
  1505.     else if (classes[mid].first > c)
  1506.         top = mid - 1;
  1507.     else
  1508.         return (int)classes[mid].class;
  1509.     }
  1510.  
  1511.     /* most other characters are "word" characters */
  1512.     return 2;
  1513. }
  1514.  
  1515. /*
  1516.  * Code for Unicode case-dependent operations.  Based on notes in
  1517.  * http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
  1518.  * This code uses simple case folding, not full case folding.
  1519.  */
  1520.  
  1521. /*
  1522.  * The following table is built by foldExtract.pl < CaseFolding.txt .
  1523.  * It must be in numeric order, because we use binary search on it.
  1524.  * An entry such as {0x41,0x5a,1,32} means that UCS-4 characters in the range
  1525.  * from 0x41 to 0x5a inclusive, stepping by 1, are folded by adding 32.
  1526.  */
  1527.  
  1528. typedef struct
  1529. {
  1530.     int rangeStart;
  1531.     int rangeEnd;
  1532.     int step;
  1533.     int offset;
  1534. } convertStruct;
  1535.  
  1536. convertStruct foldCase[] =
  1537. {
  1538.     {0x41,0x5a,1,32}, {0xb5,0xb5,-1,775}, {0xc0,0xd6,1,32},
  1539.     {0xd8,0xde,1,32}, {0x100,0x12e,2,1}, {0x130,0x130,-1,-199},
  1540.     {0x131,0x131,-1,-200}, {0x132,0x136,2,1}, {0x139,0x147,2,1},
  1541.     {0x14a,0x176,2,1}, {0x178,0x178,-1,-121}, {0x179,0x17d,2,1},
  1542.     {0x17f,0x17f,-1,-268}, {0x181,0x181,-1,210}, {0x182,0x184,2,1},
  1543.     {0x186,0x186,-1,206}, {0x187,0x187,-1,1}, {0x189,0x18a,1,205},
  1544.     {0x18b,0x18b,-1,1}, {0x18e,0x18e,-1,79}, {0x18f,0x18f,-1,202},
  1545.     {0x190,0x190,-1,203}, {0x191,0x191,-1,1}, {0x193,0x193,-1,205},
  1546.     {0x194,0x194,-1,207}, {0x196,0x196,-1,211}, {0x197,0x197,-1,209},
  1547.     {0x198,0x198,-1,1}, {0x19c,0x19c,-1,211}, {0x19d,0x19d,-1,213},
  1548.     {0x19f,0x19f,-1,214}, {0x1a0,0x1a4,2,1}, {0x1a6,0x1a6,-1,218},
  1549.     {0x1a7,0x1a7,-1,1}, {0x1a9,0x1a9,-1,218}, {0x1ac,0x1ac,-1,1},
  1550.     {0x1ae,0x1ae,-1,218}, {0x1af,0x1af,-1,1}, {0x1b1,0x1b2,1,217},
  1551.     {0x1b3,0x1b5,2,1}, {0x1b7,0x1b7,-1,219}, {0x1b8,0x1bc,4,1},
  1552.     {0x1c4,0x1c4,-1,2}, {0x1c5,0x1c5,-1,1}, {0x1c7,0x1c7,-1,2},
  1553.     {0x1c8,0x1c8,-1,1}, {0x1ca,0x1ca,-1,2}, {0x1cb,0x1db,2,1},
  1554.     {0x1de,0x1ee,2,1}, {0x1f1,0x1f1,-1,2}, {0x1f2,0x1f4,2,1},
  1555.     {0x1f6,0x1f6,-1,-97}, {0x1f7,0x1f7,-1,-56}, {0x1f8,0x21e,2,1},
  1556.     {0x222,0x232,2,1}, {0x345,0x345,-1,116}, {0x386,0x386,-1,38},
  1557.     {0x388,0x38a,1,37}, {0x38c,0x38c,-1,64}, {0x38e,0x38f,1,63},
  1558.     {0x391,0x3a1,1,32}, {0x3a3,0x3ab,1,32}, {0x3c2,0x3c2,-1,1},
  1559.     {0x3d0,0x3d0,-1,-30}, {0x3d1,0x3d1,-1,-25}, {0x3d5,0x3d5,-1,-15},
  1560.     {0x3d6,0x3d6,-1,-22}, {0x3da,0x3ee,2,1}, {0x3f0,0x3f0,-1,-54},
  1561.     {0x3f1,0x3f1,-1,-48}, {0x3f2,0x3f2,-1,-47}, {0x3f4,0x3f4,-1,-60},
  1562.     {0x3f5,0x3f5,-1,-64}, {0x400,0x40f,1,80}, {0x410,0x42f,1,32},
  1563.     {0x460,0x480,2,1}, {0x48c,0x4be,2,1}, {0x4c1,0x4c3,2,1},
  1564.     {0x4c7,0x4cb,4,1}, {0x4d0,0x4f4,2,1}, {0x4f8,0x4f8,-1,1},
  1565.     {0x531,0x556,1,48}, {0x1e00,0x1e94,2,1}, {0x1e9b,0x1e9b,-1,-58},
  1566.     {0x1ea0,0x1ef8,2,1}, {0x1f08,0x1f0f,1,-8}, {0x1f18,0x1f1d,1,-8},
  1567.     {0x1f28,0x1f2f,1,-8}, {0x1f38,0x1f3f,1,-8}, {0x1f48,0x1f4d,1,-8},
  1568.     {0x1f59,0x1f5f,2,-8}, {0x1f68,0x1f6f,1,-8}, {0x1f88,0x1f8f,1,-8},
  1569.     {0x1f98,0x1f9f,1,-8}, {0x1fa8,0x1faf,1,-8}, {0x1fb8,0x1fb9,1,-8},
  1570.     {0x1fba,0x1fbb,1,-74}, {0x1fbc,0x1fbc,-1,-9}, {0x1fbe,0x1fbe,-1,-7173},
  1571.     {0x1fc8,0x1fcb,1,-86}, {0x1fcc,0x1fcc,-1,-9}, {0x1fd8,0x1fd9,1,-8},
  1572.     {0x1fda,0x1fdb,1,-100}, {0x1fe8,0x1fe9,1,-8}, {0x1fea,0x1feb,1,-112},
  1573.     {0x1fec,0x1fec,-1,-7}, {0x1ff8,0x1ff9,1,-128}, {0x1ffa,0x1ffb,1,-126},
  1574.     {0x1ffc,0x1ffc,-1,-9}, {0x2126,0x2126,-1,-7517}, {0x212a,0x212a,-1,-8383},
  1575.     {0x212b,0x212b,-1,-8262}, {0x2160,0x216f,1,16}, {0x24b6,0x24cf,1,26},
  1576.     {0xff21,0xff3a,1,32}, {0x10400,0x10425,1,40}
  1577.     };
  1578.  
  1579. static int utf_convert(int a, convertStruct table[], int tableSize);
  1580.  
  1581. /*
  1582.  * Generic conversion function for case operations.
  1583.  * Return the converted equivalent of "a", which is a UCS-4 character.  Use
  1584.  * the given conversion "table".  Uses binary search on "table".
  1585.  */
  1586.     static int
  1587. utf_convert(a, table, tableSize)
  1588.     int            a;
  1589.     convertStruct    table[];
  1590.     int            tableSize;
  1591. {
  1592.     int start, mid, end; /* indices into table */
  1593.  
  1594.     start = 0;
  1595.     end = tableSize / sizeof(convertStruct);
  1596.     while (start < end)
  1597.     {
  1598.     /* need to search further */
  1599.     mid = (end + start) /2;
  1600.     if (table[mid].rangeEnd < a)
  1601.         start = mid + 1;
  1602.     else
  1603.         end = mid;
  1604.     }
  1605.     if (table[start].rangeStart <= a && a <= table[start].rangeEnd
  1606.         && (a - table[start].rangeStart) % table[start].step == 0)
  1607.     return (a + table[start].offset);
  1608.     else
  1609.     return a;
  1610. }
  1611.  
  1612. /*
  1613.  * Return the folded-case equivalent of "a", which is a UCS-4 character.  Uses
  1614.  * simple case folding.
  1615.  */
  1616.     int
  1617. utf_fold(a)
  1618.     int        a;
  1619. {
  1620.     return utf_convert(a, foldCase, sizeof(foldCase));
  1621. }
  1622.  
  1623. /*
  1624.  * The following tables are built by upperLowerExtract.pl < UnicodeData.txt .
  1625.  * They must be in numeric order, because we use binary search on them.
  1626.  * An entry such as {0x41,0x5a,1,32} means that UCS-4 characters in the range
  1627.  * from 0x41 to 0x5a inclusive, stepping by 1, are switched to lower (for
  1628.  * example) by adding 32.
  1629.  */
  1630. convertStruct toLower[] =
  1631. {
  1632.     {0x41,0x5a,1,32}, {0xc0,0xd6,1,32}, {0xd8,0xde,1,32},
  1633.     {0x100,0x12e,2,1}, {0x130,0x130,-1,-199}, {0x132,0x136,2,1},
  1634.     {0x139,0x147,2,1}, {0x14a,0x176,2,1}, {0x178,0x178,-1,-121},
  1635.     {0x179,0x17d,2,1}, {0x181,0x181,-1,210}, {0x182,0x184,2,1},
  1636.     {0x186,0x186,-1,206}, {0x187,0x187,-1,1}, {0x189,0x18a,1,205},
  1637.     {0x18b,0x18b,-1,1}, {0x18e,0x18e,-1,79}, {0x18f,0x18f,-1,202},
  1638.     {0x190,0x190,-1,203}, {0x191,0x191,-1,1}, {0x193,0x193,-1,205},
  1639.     {0x194,0x194,-1,207}, {0x196,0x196,-1,211}, {0x197,0x197,-1,209},
  1640.     {0x198,0x198,-1,1}, {0x19c,0x19c,-1,211}, {0x19d,0x19d,-1,213},
  1641.     {0x19f,0x19f,-1,214}, {0x1a0,0x1a4,2,1}, {0x1a6,0x1a6,-1,218},
  1642.     {0x1a7,0x1a7,-1,1}, {0x1a9,0x1a9,-1,218}, {0x1ac,0x1ac,-1,1},
  1643.     {0x1ae,0x1ae,-1,218}, {0x1af,0x1af,-1,1}, {0x1b1,0x1b2,1,217},
  1644.     {0x1b3,0x1b5,2,1}, {0x1b7,0x1b7,-1,219}, {0x1b8,0x1bc,4,1},
  1645.     {0x1c4,0x1ca,3,2}, {0x1cd,0x1db,2,1}, {0x1de,0x1ee,2,1},
  1646.     {0x1f1,0x1f1,-1,2}, {0x1f4,0x1f4,-1,1}, {0x1f6,0x1f6,-1,-97},
  1647.     {0x1f7,0x1f7,-1,-56}, {0x1f8,0x21e,2,1}, {0x222,0x232,2,1},
  1648.     {0x386,0x386,-1,38}, {0x388,0x38a,1,37}, {0x38c,0x38c,-1,64},
  1649.     {0x38e,0x38f,1,63}, {0x391,0x3a1,1,32}, {0x3a3,0x3ab,1,32},
  1650.     {0x3da,0x3ee,2,1}, {0x3f4,0x3f4,-1,-60}, {0x400,0x40f,1,80},
  1651.     {0x410,0x42f,1,32}, {0x460,0x480,2,1}, {0x48c,0x4be,2,1},
  1652.     {0x4c1,0x4c3,2,1}, {0x4c7,0x4cb,4,1}, {0x4d0,0x4f4,2,1},
  1653.     {0x4f8,0x4f8,-1,1}, {0x531,0x556,1,48}, {0x1e00,0x1e94,2,1},
  1654.     {0x1ea0,0x1ef8,2,1}, {0x1f08,0x1f0f,1,-8}, {0x1f18,0x1f1d,1,-8},
  1655.     {0x1f28,0x1f2f,1,-8}, {0x1f38,0x1f3f,1,-8}, {0x1f48,0x1f4d,1,-8},
  1656.     {0x1f59,0x1f5f,2,-8}, {0x1f68,0x1f6f,1,-8}, {0x1fb8,0x1fb9,1,-8},
  1657.     {0x1fba,0x1fbb,1,-74}, {0x1fc8,0x1fcb,1,-86}, {0x1fd8,0x1fd9,1,-8},
  1658.     {0x1fda,0x1fdb,1,-100}, {0x1fe8,0x1fe9,1,-8}, {0x1fea,0x1feb,1,-112},
  1659.     {0x1fec,0x1fec,-1,-7}, {0x1ff8,0x1ff9,1,-128}, {0x1ffa,0x1ffb,1,-126},
  1660.     {0x2126,0x2126,-1,-7517}, {0x212a,0x212a,-1,-8383},
  1661.     {0x212b,0x212b,-1,-8262}, {0xff21,0xff3a,1,32}, {0x10400,0x10425,1,40}
  1662. };
  1663.  
  1664. convertStruct toUpper[] =
  1665. {
  1666.     {0x61,0x7a,1,-32}, {0xb5,0xb5,-1,743}, {0xe0,0xf6,1,-32},
  1667.     {0xf8,0xfe,1,-32}, {0xff,0xff,-1,121}, {0x101,0x12f,2,-1},
  1668.     {0x131,0x131,-1,-232}, {0x133,0x137,2,-1}, {0x13a,0x148,2,-1},
  1669.     {0x14b,0x177,2,-1}, {0x17a,0x17e,2,-1}, {0x17f,0x17f,-1,-300},
  1670.     {0x183,0x185,2,-1}, {0x188,0x18c,4,-1}, {0x192,0x192,-1,-1},
  1671.     {0x195,0x195,-1,97}, {0x199,0x1a1,8,-1}, {0x1a3,0x1a5,2,-1},
  1672.     {0x1a8,0x1ad,5,-1}, {0x1b0,0x1b4,4,-1}, {0x1b6,0x1b9,3,-1},
  1673.     {0x1bd,0x1bd,-1,-1}, {0x1bf,0x1bf,-1,56}, {0x1c5,0x1c6,1,-1},
  1674.     {0x1c8,0x1c9,1,-1}, {0x1cb,0x1cc,1,-1}, {0x1ce,0x1dc,2,-1},
  1675.     {0x1dd,0x1dd,-1,-79}, {0x1df,0x1ef,2,-1}, {0x1f2,0x1f3,1,-1},
  1676.     {0x1f5,0x1f9,4,-1}, {0x1fb,0x21f,2,-1}, {0x223,0x233,2,-1},
  1677.     {0x253,0x253,-1,-210}, {0x254,0x254,-1,-206}, {0x256,0x257,1,-205},
  1678.     {0x259,0x259,-1,-202}, {0x25b,0x25b,-1,-203}, {0x260,0x260,-1,-205},
  1679.     {0x263,0x263,-1,-207}, {0x268,0x268,-1,-209}, {0x269,0x26f,6,-211},
  1680.     {0x272,0x272,-1,-213}, {0x275,0x275,-1,-214}, {0x280,0x283,3,-218},
  1681.     {0x288,0x288,-1,-218}, {0x28a,0x28b,1,-217}, {0x292,0x292,-1,-219},
  1682.     {0x3ac,0x3ac,-1,-38}, {0x3ad,0x3af,1,-37}, {0x3b1,0x3c1,1,-32},
  1683.     {0x3c2,0x3c2,-1,-31}, {0x3c3,0x3cb,1,-32}, {0x3cc,0x3cc,-1,-64},
  1684.     {0x3cd,0x3ce,1,-63}, {0x3d0,0x3d0,-1,-62}, {0x3d1,0x3d1,-1,-57},
  1685.     {0x3d5,0x3d5,-1,-47}, {0x3d6,0x3d6,-1,-54}, {0x3db,0x3ef,2,-1},
  1686.     {0x3f0,0x3f0,-1,-86}, {0x3f1,0x3f1,-1,-80}, {0x3f2,0x3f2,-1,-79},
  1687.     {0x3f5,0x3f5,-1,-96}, {0x430,0x44f,1,-32}, {0x450,0x45f,1,-80},
  1688.     {0x461,0x481,2,-1}, {0x48d,0x4bf,2,-1}, {0x4c2,0x4c4,2,-1},
  1689.     {0x4c8,0x4cc,4,-1}, {0x4d1,0x4f5,2,-1}, {0x4f9,0x4f9,-1,-1},
  1690.     {0x561,0x586,1,-48}, {0x1e01,0x1e95,2,-1}, {0x1e9b,0x1e9b,-1,-59},
  1691.     {0x1ea1,0x1ef9,2,-1}, {0x1f00,0x1f07,1,8}, {0x1f10,0x1f15,1,8},
  1692.     {0x1f20,0x1f27,1,8}, {0x1f30,0x1f37,1,8}, {0x1f40,0x1f45,1,8},
  1693.     {0x1f51,0x1f57,2,8}, {0x1f60,0x1f67,1,8}, {0x1f70,0x1f71,1,74},
  1694.     {0x1f72,0x1f75,1,86}, {0x1f76,0x1f77,1,100}, {0x1f78,0x1f79,1,128},
  1695.     {0x1f7a,0x1f7b,1,112}, {0x1f7c,0x1f7d,1,126}, {0x1f80,0x1f87,1,8},
  1696.     {0x1f90,0x1f97,1,8}, {0x1fa0,0x1fa7,1,8}, {0x1fb0,0x1fb1,1,8},
  1697.     {0x1fb3,0x1fb3,-1,9}, {0x1fbe,0x1fbe,-1,-7205}, {0x1fc3,0x1fc3,-1,9},
  1698.     {0x1fd0,0x1fd1,1,8}, {0x1fe0,0x1fe1,1,8}, {0x1fe5,0x1fe5,-1,7},
  1699.     {0x1ff3,0x1ff3,-1,9}, {0xff41,0xff5a,1,-32}, {0x10428,0x1044d,1,-40}
  1700. };
  1701.  
  1702. /*
  1703.  * Return the upper-case equivalent of "a", which is a UCS-4 character.  Use
  1704.  * simple case folding.
  1705.  */
  1706.     int
  1707. utf_toupper(a)
  1708.     int        a;
  1709. {
  1710.     if (a < 128)
  1711.     return toupper(a);
  1712.     return utf_convert(a, toUpper, sizeof(toUpper));
  1713. }
  1714.  
  1715.     int
  1716. utf_islower(a)
  1717.     int        a;
  1718. {
  1719.     return (utf_toupper(a) != a);
  1720. }
  1721.  
  1722. /*
  1723.  * Return the lower-case equivalent of "a", which is a UCS-4 character.  Use
  1724.  * simple case folding.
  1725.  */
  1726.     int
  1727. utf_tolower(a)
  1728.     int        a;
  1729. {
  1730.     if (a < 128)
  1731.     return tolower(a);
  1732.     return utf_convert(a, toLower, sizeof(toLower));
  1733. }
  1734.  
  1735.     int
  1736. utf_isupper(a)
  1737.     int        a;
  1738. {
  1739.     return (utf_tolower(a) != a);
  1740. }
  1741.  
  1742. /*
  1743.  * Version of strnicmp() that handles multi-byte characters.
  1744.  * Needed for Big5, Sjift-JIS and UTF-8 encoding.  Other DBCS encodings can
  1745.  * probably use strnicmp(), because there are no ASCII characters in the
  1746.  * second byte.
  1747.  * Returns zero if s1 and s2 are equal (ignoring case), the difference between
  1748.  * two characters otherwise.
  1749.  */
  1750.     int
  1751. mb_strnicmp(s1, s2, n)
  1752.     char_u    *s1, *s2;
  1753.     int        n;
  1754. {
  1755.     int        i, l;
  1756.     int        cdiff;
  1757.  
  1758.     for (i = 0; i < n; i += l)
  1759.     {
  1760.     if (enc_utf8)
  1761.         l = utf_ptr2len_check(s1 + i);  /* exclude composing chars */
  1762.     else
  1763.         l = (*mb_ptr2len_check)(s1 + i);
  1764.     if (l <= 1)
  1765.     {
  1766.         /* Single byte: first check normally, then with ignore case. */
  1767.         if (s1[i] != s2[i])
  1768.         {
  1769.         cdiff = TO_LOWER(s1[i]) - TO_LOWER(s2[i]);
  1770.         if (cdiff != 0)
  1771.             return cdiff;
  1772.         }
  1773.         else if (s1[i] == NUL)
  1774.         return 0;
  1775.     }
  1776.     else
  1777.     {
  1778.         /* For multi-byte only ignore case for Unicode. */
  1779.         if (l > n - i)
  1780.         l = n - i;
  1781.         if (enc_utf8)
  1782.         cdiff = utf_fold(utf_ptr2char(s1 + i))
  1783.                          - utf_fold(utf_ptr2char(s2 + i));
  1784.         else
  1785.         cdiff =  STRNCMP(s1 + i, s2 + i, l);
  1786.         if (cdiff != 0)
  1787.         return cdiff;
  1788.     }
  1789.     }
  1790.     return 0;
  1791. }
  1792.  
  1793. /*
  1794.  * "g8": show bytes of the UTF-8 char under the cursor.  Doesn't matter what
  1795.  * 'encoding' has been set to.
  1796.  */
  1797.     void
  1798. show_utf8()
  1799. {
  1800.     int        len;
  1801.     char_u    *line;
  1802.     int        clen;
  1803.     int        i;
  1804.  
  1805.     /* Get the byte length of the char under the cursor, including composing
  1806.      * characters. */
  1807.     line = ml_get_cursor();
  1808.     len = utfc_ptr2len_check(line);
  1809.     if (len == 0)
  1810.     {
  1811.     MSG("NUL");
  1812.     return;
  1813.     }
  1814.  
  1815.     IObuff[0] = NUL;
  1816.     clen = 0;
  1817.     for (i = 0; i < len; ++i)
  1818.     {
  1819.     if (clen == 0)
  1820.     {
  1821.         /* start of (composing) character, get its length */
  1822.         if (i > 0)
  1823.         STRCAT(IObuff, "+ ");
  1824.         clen = utf_ptr2len_check(line + i);
  1825.     }
  1826.     sprintf((char *)IObuff + STRLEN(IObuff), "%02x ", line[i]);
  1827.     --clen;
  1828.     }
  1829.  
  1830.     msg(IObuff);
  1831. }
  1832.  
  1833. /*
  1834.  * mb_head_off() function pointer.
  1835.  * Return offset from "p" to the first byte of the character it points into.
  1836.  * Returns 0 when already at the first byte of a character.
  1837.  */
  1838. /*ARGSUSED*/
  1839.     int
  1840. latin_head_off(base, p)
  1841.     char_u    *base;
  1842.     char_u    *p;
  1843. {
  1844.     return 0;
  1845. }
  1846.  
  1847.     int
  1848. dbcs_head_off(base, p)
  1849.     char_u    *base;
  1850.     char_u    *p;
  1851. {
  1852.     char_u    *q;
  1853.  
  1854.     /* It can't be a trailing byte when not using DBCS, at the start of the
  1855.      * string or the previous byte can't start a double-byte. */
  1856.     if (p <= base || MB_BYTE2LEN(p[-1]) == 1)
  1857.     return 0;
  1858.  
  1859.     /* This is slow: need to start at the base and go forward until the
  1860.      * byte we are looking for.  Return 1 when we went past it, 0 otherwise. */
  1861.     q = base;
  1862.     while (q < p)
  1863.     q += dbcs_ptr2len_check(q);
  1864.     return (q == p) ? 0 : 1;
  1865. }
  1866.  
  1867. #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(PROTO)
  1868. /*
  1869.  * Special version of dbcs_head_off() that works for ScreenLines[], where
  1870.  * single-width DBCS_JPNU characters are stored separately.
  1871.  */
  1872.     int
  1873. dbcs_screen_head_off(base, p)
  1874.     char_u    *base;
  1875.     char_u    *p;
  1876. {
  1877.     char_u    *q;
  1878.  
  1879.     /* It can't be a trailing byte when not using DBCS, at the start of the
  1880.      * string or the previous byte can't start a double-byte.
  1881.      * For euc-jp an 0x8e byte in the previous cell always means we have a
  1882.      * lead byte in the current cell. */
  1883.     if (p <= base
  1884.         || (enc_dbcs == DBCS_JPNU && p[-1] == 0x8e)
  1885.         || MB_BYTE2LEN(p[-1]) == 1)
  1886.     return 0;
  1887.  
  1888.     /* This is slow: need to start at the base and go forward until the
  1889.      * byte we are looking for.  Return 1 when we went past it, 0 otherwise.
  1890.      * For DBCS_JPNU look out for 0x8e, which means the second byte is not
  1891.      * stored as the next byte. */
  1892.     q = base;
  1893.     while (q < p)
  1894.     {
  1895.     if (enc_dbcs == DBCS_JPNU && *q == 0x8e)
  1896.         ++q;
  1897.     else
  1898.         q += dbcs_ptr2len_check(q);
  1899.     }
  1900.     return (q == p) ? 0 : 1;
  1901. }
  1902. #endif
  1903.  
  1904.     int
  1905. utf_head_off(base, p)
  1906.     char_u    *base;
  1907.     char_u    *p;
  1908. {
  1909.     char_u    *q;
  1910.     char_u    *s;
  1911.  
  1912.     if (*p < 0x80)        /* be quick for ASCII */
  1913.     return 0;
  1914.  
  1915.     /* Skip backwards over trailing bytes: 10xx.xxxx
  1916.      * Skip backwards again if on a composing char. */
  1917.     for (q = p; ; --q)
  1918.     {
  1919.     /* Move s to the last byte of this char. */
  1920.     for (s = q; (s[1] & 0xc0) == 0x80; ++s)
  1921.         ;
  1922.     /* Move q to the first byte of this char. */
  1923.     while (q > base && (*q & 0xc0) == 0x80)
  1924.         --q;
  1925.     /* Check for illegal sequence. */
  1926.     if (utf8len_tab[*q] != (int)(s - q + 1))
  1927.         return 0;
  1928.     if (q <= base || !utf_iscomposing(utf_ptr2char(q)))
  1929.         break;
  1930.     }
  1931.  
  1932.     return (int)(p - q);
  1933. }
  1934.  
  1935. /*
  1936.  * Return the offset from "p" to the first byte of a character.  When "p" is
  1937.  * at the start of a character 0 is returned, otherwise the offset to the next
  1938.  * character.  Can start anywhere in a stream of bytes.
  1939.  */
  1940.     int
  1941. mb_off_next(base, p)
  1942.     char_u    *base;
  1943.     char_u    *p;
  1944. {
  1945.     int        i;
  1946.     int        j;
  1947.  
  1948.     if (enc_utf8)
  1949.     {
  1950.     if (*p < 0x80)        /* be quick for ASCII */
  1951.         return 0;
  1952.  
  1953.     /* Find the next character that isn't 10xx.xxxx */
  1954.     for (i = 0; (p[i] & 0xc0) == 0x80; ++i)
  1955.         ;
  1956.     if (i > 0)
  1957.     {
  1958.         /* Check for illegal sequence. */
  1959.         for (j = 0; p - j > base; ++j)
  1960.         if ((p[-j] & 0xc0) != 0x80)
  1961.             break;
  1962.         if (utf8len_tab[p[-j]] != i + j)
  1963.         return 0;
  1964.     }
  1965.     return i;
  1966.     }
  1967.  
  1968.     /* Only need to check if we're on a trail byte, it doesn't matter if we
  1969.      * want the offset to the next or current character. */
  1970.     return (*mb_head_off)(base, p);
  1971. }
  1972.  
  1973. /*
  1974.  * Return the offset from "p" to the last byte of the character it points
  1975.  * into.  Can start anywhere in a stream of bytes.
  1976.  */
  1977.     int
  1978. mb_tail_off(base, p)
  1979.     char_u    *base;
  1980.     char_u    *p;
  1981. {
  1982.     int        i;
  1983.     int        j;
  1984.  
  1985.     if (*p == NUL)
  1986.     return 0;
  1987.  
  1988.     if (enc_utf8)
  1989.     {
  1990.     /* Find the last character that is 10xx.xxxx */
  1991.     for (i = 0; (p[i + 1] & 0xc0) == 0x80; ++i)
  1992.         ;
  1993.     /* Check for illegal sequence. */
  1994.     for (j = 0; p - j > base; ++j)
  1995.         if ((p[-j] & 0xc0) != 0x80)
  1996.         break;
  1997.     if (utf8len_tab[p[-j]] != i + j + 1)
  1998.         return 0;
  1999.     return i;
  2000.     }
  2001.  
  2002.     /* It can't be the first byte if a double-byte when not using DBCS, at the
  2003.      * end of the string or the byte can't start a double-byte. */
  2004.     if (enc_dbcs == 0 || p[1] == NUL || MB_BYTE2LEN(*p) == 1)
  2005.     return 0;
  2006.  
  2007.     /* Return 1 when on the lead byte, 0 when on the tail byte. */
  2008.     return 1 - dbcs_head_off(base, p);
  2009. }
  2010.  
  2011. #if defined(FEAT_GUI) || defined(PROTO)
  2012. /*
  2013.  * Special version of mb_tail_off() for use in ScreenLines[].
  2014.  */
  2015.     int
  2016. dbcs_screen_tail_off(base, p)
  2017.     char_u    *base;
  2018.     char_u    *p;
  2019. {
  2020.     /* It can't be the first byte if a double-byte when not using DBCS, at the
  2021.      * end of the string or the byte can't start a double-byte.
  2022.      * For euc-jp an 0x8e byte always means we have a lead byte in the current
  2023.      * cell. */
  2024.     if (*p == NUL || p[1] == NUL
  2025.         || (enc_dbcs == DBCS_JPNU && *p == 0x8e)
  2026.         || MB_BYTE2LEN(*p) == 1)
  2027.     return 0;
  2028.  
  2029.     /* Return 1 when on the lead byte, 0 when on the tail byte. */
  2030.     return 1 - dbcs_screen_head_off(base, p);
  2031. }
  2032. #endif
  2033.  
  2034. /*
  2035.  * If the cursor moves on an trail byte, set the cursor on the lead byte.
  2036.  * Thus it moves left if necessary.
  2037.  * Return TRUE when the cursor was adjusted.
  2038.  */
  2039.     void
  2040. mb_adjust_cursor()
  2041. {
  2042.     mb_adjustpos(&curwin->w_cursor);
  2043. }
  2044.  
  2045. /*
  2046.  * Adjust position "*lp" to point to the first byte of a multi-byte character.
  2047.  * If it points to a tail byte it's moved backwards to the head byte.
  2048.  */
  2049.     void
  2050. mb_adjustpos(lp)
  2051.     pos_T    *lp;
  2052. {
  2053.     char_u    *p;
  2054.  
  2055.     if (lp->col > 0)
  2056.     {
  2057.     p = ml_get(lp->lnum);
  2058.     lp->col -= (*mb_head_off)(p, p + lp->col);
  2059.     }
  2060. }
  2061.  
  2062. /*
  2063.  * Return a pointer to the character before "*p", if there is one.
  2064.  */
  2065.     char_u *
  2066. mb_prevptr(line, p)
  2067.     char_u *line;    /* start of the string */
  2068.     char_u *p;
  2069. {
  2070.     if (p > line)
  2071.     p = p - (*mb_head_off)(line, p - 1) - 1;
  2072.     return p;
  2073. }
  2074.  
  2075. /*
  2076.  * Return the character length of "str".  multi-byte characters counts as one.
  2077.  */
  2078.     int
  2079. mb_charlen(str)
  2080.     char_u    *str;
  2081. {
  2082.     int count;
  2083.  
  2084.     if (str == NULL)
  2085.     return 0;
  2086.  
  2087.     for (count = 0; *str != NUL; count++)
  2088.     str += (*mb_ptr2len_check)(str);
  2089.  
  2090.     return count;
  2091. }
  2092.  
  2093. /*
  2094.  * Decrement position "lp" by one character, taking care of multi-byte chars.
  2095.  */
  2096.     int
  2097. mb_dec(lp)
  2098.     pos_T    *lp;
  2099. {
  2100.     if (lp->col > 0)        /* still within line */
  2101.     {
  2102.     --lp->col;
  2103.     mb_adjustpos(lp);
  2104.     return 0;
  2105.     }
  2106.     if (lp->lnum > 1)        /* there is a prior line */
  2107.     {
  2108.     lp->lnum--;
  2109.     lp->col = (colnr_T)STRLEN(ml_get(lp->lnum));
  2110.     mb_adjustpos(lp);
  2111.     return 1;
  2112.     }
  2113.     return -1;            /* at start of file */
  2114. }
  2115.  
  2116. /*
  2117.  * Try to un-escape a multi-byte character.
  2118.  * Used for the "to" and "from" part of a mapping.
  2119.  * Return the un-escaped string if it is a multi-byte character, and advance
  2120.  * "pp" to just after the bytes that formed it.
  2121.  * Return NULL if no multi-byte char was found.
  2122.  */
  2123.     char_u *
  2124. mb_unescape(pp)
  2125.     char_u **pp;
  2126. {
  2127.     static char_u    buf[MB_MAXBYTES + 1];
  2128.     int            n, m = 0;
  2129.     char_u        *str = *pp;
  2130.  
  2131.     /* Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI
  2132.      * KS_EXTRA KE_CSI to CSI. */
  2133.     for (n = 0; str[n] != NUL && m <= MB_MAXBYTES; ++n)
  2134.     {
  2135.     if (str[n] == K_SPECIAL
  2136.         && str[n + 1] == KS_SPECIAL
  2137.         && str[n + 2] == KE_FILLER)
  2138.     {
  2139.         buf[m++] = K_SPECIAL;
  2140.         n += 2;
  2141.     }
  2142. # ifdef FEAT_GUI
  2143.     else if (str[n] == CSI
  2144.         && str[n + 1] == KS_EXTRA
  2145.         && str[n + 2] == (int)KE_CSI)
  2146.     {
  2147.         buf[m++] = CSI;
  2148.         n += 2;
  2149.     }
  2150. # endif
  2151.     else if (str[n] == K_SPECIAL
  2152. # ifdef FEAT_GUI
  2153.         || str[n] == CSI
  2154. # endif
  2155.         )
  2156.         break;        /* a special key can't be a multibyte char */
  2157.     else
  2158.         buf[m++] = str[n];
  2159.     buf[m] = NUL;
  2160.  
  2161.     /* Return a multi-byte character if it's found.  An illegal sequence
  2162.      * will result in a 1 here. */
  2163.     if ((*mb_ptr2len_check)(buf) > 1)
  2164.     {
  2165.         *pp = str + n + 1;
  2166.         return buf;
  2167.     }
  2168.     }
  2169.     return NULL;
  2170. }
  2171.  
  2172. #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(PROTO)
  2173. /*
  2174.  * Return TRUE if the character at "row"/"col" on the screen is the left side
  2175.  * of a double-width character.
  2176.  * Caller must make sure "row" and "col" are not invalid!
  2177.  */
  2178.     int
  2179. mb_lefthalve(row, col)
  2180.     int        row;
  2181.     int        col;
  2182. {
  2183. #ifdef FEAT_HANGULIN
  2184.     if (composing_hangul)
  2185.     return TRUE;
  2186. #endif
  2187.     if (enc_dbcs != 0)
  2188.     return dbcs_off2cells(LineOffset[row] + col) > 1;
  2189.     if (enc_utf8)
  2190.     return (col + 1 < Columns
  2191.         && ScreenLines[LineOffset[row] + col + 1] == 0);
  2192.     return FALSE;
  2193. }
  2194. #endif
  2195.  
  2196. #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(PROTO)
  2197. /*
  2198.  * Correct a position on the screen, if it's the right halve of a double-wide
  2199.  * char move it to the left halve.  Returns the corrected column.
  2200.  */
  2201.     int
  2202. mb_fix_col(col, row)
  2203.     int        col;
  2204.     int        row;
  2205. {
  2206.     col = check_col(col);
  2207.     row = check_row(row);
  2208.     if (has_mbyte && ScreenLines != NULL && col > 0
  2209.         && ((enc_dbcs
  2210.             && ScreenLines[LineOffset[row] + col] != NUL
  2211.             && dbcs_screen_head_off(ScreenLines + LineOffset[row],
  2212.                      ScreenLines + LineOffset[row] + col))
  2213.         || (enc_utf8 && ScreenLines[LineOffset[row] + col] == 0)))
  2214.     --col;
  2215.     return col;
  2216. }
  2217. #endif
  2218.  
  2219. /*
  2220.  * Skip the Vim specific head of a 'encoding' name.
  2221.  */
  2222.     char_u *
  2223. enc_skip(p)
  2224.     char_u    *p;
  2225. {
  2226.     if (STRNCMP(p, "2byte-", 6) == 0)
  2227.     return p + 6;
  2228.     if (STRNCMP(p, "8bit-", 5) == 0)
  2229.     return p + 5;
  2230.     return p;
  2231. }
  2232.  
  2233. /*
  2234.  * Find the canonical name for encoding "enc".
  2235.  * When the name isn't recognized, returns "enc" itself, but with all lower
  2236.  * case characters and '_' replaced with '-'.
  2237.  * Returns an allocated string.  NULL for out-of-memory.
  2238.  */
  2239.     char_u *
  2240. enc_canonize(enc)
  2241.     char_u    *enc;
  2242. {
  2243.     char_u    *r;
  2244.     char_u    *p, *s;
  2245.     int        i;
  2246.  
  2247.     /* copy "enc" to allocted memory, with room for two '-' */
  2248.     r = alloc((unsigned)(STRLEN(enc) + 3));
  2249.     if (r != NULL)
  2250.     {
  2251.     /* Make it all lower case and replace '_' with '-'. */
  2252.     p = r;
  2253.     for (s = enc; *s != NUL; ++s)
  2254.     {
  2255.         if (*s == '_')
  2256.         *p++ = '-';
  2257.         else
  2258.         *p++ = TO_LOWER(*s);
  2259.     }
  2260.     *p = NUL;
  2261.  
  2262.     /* Skip "2byte-" and "8bit-". */
  2263.     p = enc_skip(r);
  2264.  
  2265.     /* "iso8859" -> "iso-8859" */
  2266.     if (STRNCMP(p, "iso8859", 7) == 0)
  2267.     {
  2268.         mch_memmove(p + 4, p + 3, STRLEN(p + 2));
  2269.         p[3] = '-';
  2270.     }
  2271.  
  2272.     /* "iso-8859n" -> "iso-8859-n" */
  2273.     if (STRNCMP(p, "iso-8859", 8) == 0 && p[8] != '-')
  2274.     {
  2275.         mch_memmove(p + 9, p + 8, STRLEN(p + 7));
  2276.         p[8] = '-';
  2277.     }
  2278.  
  2279.     /* "latin-N" -> "latinN" */
  2280.     if (STRNCMP(p, "latin-", 6) == 0)
  2281.         mch_memmove(p + 5, p + 6, STRLEN(p + 5));
  2282.  
  2283.     if (enc_canon_search(p) >= 0)
  2284.     {
  2285.         /* canonical name can be used unmodified */
  2286.         if (p != r)
  2287.         mch_memmove(r, p, STRLEN(p) + 1);
  2288.     }
  2289.     else if ((i = enc_alias_search(p)) >= 0)
  2290.     {
  2291.         /* alias recognized, get canonical name */
  2292.         vim_free(r);
  2293.         r = vim_strsave((char_u *)enc_canon_table[i].name);
  2294.     }
  2295.     }
  2296.     return r;
  2297. }
  2298.  
  2299. /*
  2300.  * Search for an encoding alias of "name".
  2301.  * Returns -1 when not found.
  2302.  */
  2303.     static int
  2304. enc_alias_search(name)
  2305.     char_u    *name;
  2306. {
  2307.     int        i;
  2308.  
  2309.     for (i = 0; enc_alias_table[i].name != NULL; ++i)
  2310.     if (STRCMP(name, enc_alias_table[i].name) == 0)
  2311.         return enc_alias_table[i].canon;
  2312.     return -1;
  2313. }
  2314.  
  2315. #ifdef HAVE_LANGINFO_H
  2316. # include <langinfo.h>
  2317. #endif
  2318.  
  2319. /*
  2320.  * Return the default value for 'encoding' in an allocated string.
  2321.  * Returns NULL when out of memory or no usable default could be found.
  2322.  */
  2323.     int
  2324. enc_default()
  2325. {
  2326. #ifndef WIN3264
  2327.     char    *s;
  2328.     char    *p;
  2329.     int        i;
  2330. #endif
  2331.     char    buf[50];
  2332.     char_u    *save_enc;
  2333. #ifdef WIN3264
  2334.     long    acp = GetACP();
  2335.  
  2336.     if (acp == 1200)
  2337.     STRCPY(buf, "ucs-2le");
  2338.     else if (acp == 1252)
  2339.     STRCPY(buf, "latin1");
  2340.     else
  2341.     sprintf(buf, "cp%ld", acp);
  2342. #else
  2343. # ifdef HAVE_NL_LANGINFO_CODESET
  2344.     if ((s = nl_langinfo(CODESET)) == NULL || *s == NUL)
  2345. # endif
  2346. # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
  2347.     if ((s = setlocale(LC_CTYPE, NULL)) == NULL || *s == NUL)
  2348. # endif
  2349.         if ((s = getenv("LC_ALL")) == NULL || *s == NUL)
  2350.         if ((s = getenv("LC_CTYPE")) == NULL || *s == NUL)
  2351.             s = getenv("LANG");
  2352.  
  2353.     /* The most generic locale format is:
  2354.      * language[_territory][.codeset][@modifier][+special][,[sponsor][_revision]]
  2355.      * If there is a '.' remove the part before it.
  2356.      * if there is something after the codeset, remove it.
  2357.      * Make the name lowercase and replace '_' with '-'.
  2358.      * Exception: "ja_JP.EUC" == "euc-jp", "zh_CN.EUC" = "euc-cn",
  2359.      * "ko_KR.EUC" == "euc-kr"
  2360.      */
  2361.     if ((p = (char *)vim_strchr((char_u *)s, '.')) != NULL)
  2362.     {
  2363.     if (p > s + 2 && STRNICMP(p + 1, "EUC", 3) == 0
  2364.             && !isalnum((int)p[4]) && p[4] != '-' && p[-3] == '_')
  2365.     {
  2366.         /* copy "XY.EUC" to "euc-XY" to buf[10] */
  2367.         STRCPY(buf + 10, "euc-");
  2368.         buf[14] = p[-2];
  2369.         buf[15] = p[-1];
  2370.         buf[16] = 0;
  2371.         s = buf + 10;
  2372.     }
  2373.     else
  2374.         s = p + 1;
  2375.     }
  2376.     for (i = 0; s[i] != NUL && i < sizeof(buf) - 1; ++i)
  2377.     {
  2378.     if (s[i] == '_' || s[i] == '-')
  2379.         buf[i] = '-';
  2380.     else if (isalnum((int)s[i]))
  2381.         buf[i] = TO_LOWER(s[i]);
  2382.     else
  2383.         break;
  2384.     }
  2385.     buf[i] = NUL;
  2386. #endif
  2387.  
  2388.     /*
  2389.      * Try setting 'encoding' and check if the value is valid.
  2390.      * If not, go back to the default "latin1".
  2391.      */
  2392.     save_enc = p_enc;
  2393.     p_enc = enc_canonize((char_u *)buf);
  2394.     if (p_enc != NULL && mb_init() == NULL)
  2395.     return OK;
  2396.     vim_free(p_enc);
  2397.     p_enc = save_enc;
  2398.  
  2399.     return FAIL;
  2400. }
  2401.  
  2402. # if defined(USE_ICONV) || defined(PROTO)
  2403.  
  2404. static char_u *iconv_string __ARGS((iconv_t fd, char_u *str, int slen));
  2405.  
  2406. /*
  2407.  * Call iconv_open() with a check if iconv() works properly (there are broken
  2408.  * versions).
  2409.  * Returns (void *)-1 if failed.
  2410.  * (should return iconv_t, but that causes problems with prototypes).
  2411.  */
  2412.     void *
  2413. my_iconv_open(to, from)
  2414.     char_u    *to;
  2415.     char_u    *from;
  2416. {
  2417.     iconv_t    fd;
  2418. #define ICONV_TESTLEN 400
  2419.     char_u    tobuf[ICONV_TESTLEN];
  2420.     char    *p;
  2421.     size_t    tolen;
  2422.     static int    iconv_ok = -1;
  2423.  
  2424.     if (iconv_ok == FALSE)
  2425.     return (void *)-1;    /* detected a broken iconv() previously */
  2426.  
  2427. #ifdef DYNAMIC_ICONV
  2428.     /* Check if the iconv.dll can be found. */
  2429.     if (!iconv_enabled())
  2430.     return (void *)-1;
  2431. #endif
  2432.  
  2433.     fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from));
  2434.  
  2435.     if (fd != (iconv_t)-1 && iconv_ok == -1)
  2436.     {
  2437.     /*
  2438.      * Do a dummy iconv() call to check if it actually works.  There is a
  2439.      * version of iconv() on Linux that is broken.  We can't ignore it,
  2440.      * because it's wide-spread.  The symptoms are that after outputting
  2441.      * the initial shift state the "to" pointer is NULL and conversion
  2442.      * stops for no apparent reason after about 8160 characters.
  2443.      */
  2444.     p = (char *)tobuf;
  2445.     tolen = ICONV_TESTLEN;
  2446.     (void)iconv(fd, NULL, NULL, &p, &tolen);
  2447.     if (p == NULL)
  2448.     {
  2449.         iconv_ok = FALSE;
  2450.         iconv_close(fd);
  2451.         fd = (iconv_t)-1;
  2452.     }
  2453.     else
  2454.         iconv_ok = TRUE;
  2455.     }
  2456.  
  2457.     return (void *)fd;
  2458. }
  2459.  
  2460. /*
  2461.  * Convert the string "str[slen]" with iconv().
  2462.  * Returns the converted string in allocated memory.  NULL for an error.
  2463.  */
  2464.     static char_u *
  2465. iconv_string(fd, str, slen)
  2466.     iconv_t    fd;
  2467.     char_u    *str;
  2468.     int        slen;
  2469. {
  2470.     const char    *from;
  2471.     size_t    fromlen;
  2472.     char    *to;
  2473.     size_t    tolen;
  2474.     size_t    len = 0;
  2475.     size_t    done = 0;
  2476.     char_u    *result = NULL;
  2477.     char_u    *p;
  2478.     int        l;
  2479.  
  2480.     from = (char *)str;
  2481.     fromlen = slen;
  2482.     for (;;)
  2483.     {
  2484.     if (len == 0 || ICONV_ERRNO == E2BIG)
  2485.     {
  2486.         /* Allocate enough room for most conversions.  When re-allocating
  2487.          * increase the buffer size. */
  2488.         len = len + fromlen * 2 + 40;
  2489.         p = alloc((unsigned)len);
  2490.         if (p != NULL && done > 0)
  2491.         mch_memmove(p, result, done);
  2492.         vim_free(result);
  2493.         result = p;
  2494.         if (result == NULL)    /* out of memory */
  2495.         break;
  2496.     }
  2497.  
  2498.     to = (char *)result + done;
  2499.     tolen = len - done - 2;
  2500.     if (iconv(fd, &from, &fromlen, &to, &tolen) != (size_t)-1)
  2501.     {
  2502.         /* Finished, append a NUL. */
  2503.         *to = NUL;
  2504.         break;
  2505.     }
  2506.     if (ICONV_ERRNO == EILSEQ)
  2507.     {
  2508.         /* Can't convert: insert a '?' and skip a character.  This assumes
  2509.          * conversion from 'encoding' to something else.  In other
  2510.          * situations we don't know what to skip anyway. */
  2511.         *to++ = '?';
  2512.         if ((*mb_ptr2cells)((char_u *)from) > 1)
  2513.         *to++ = '?';
  2514.         l = (*mb_ptr2len_check)((char_u *)from);
  2515.         from += l;
  2516.         fromlen -= l;
  2517.     }
  2518.     else if (ICONV_ERRNO != E2BIG)
  2519.     {
  2520.         /* conversion failed */
  2521.         vim_free(result);
  2522.         result = NULL;
  2523.         break;
  2524.     }
  2525.     /* Not enough room or skipping illegal sequence. */
  2526.     done = to - (char *)result;
  2527.     }
  2528.     return result;
  2529. }
  2530.  
  2531. #  if defined(DYNAMIC_ICONV) || defined(PROTO)
  2532. /*
  2533.  * Dynamically load the "iconv.dll" on Win32.
  2534.  */
  2535.  
  2536. #ifndef DYNAMIC_ICONV        /* just generating prototypes */
  2537. # define HINSTANCE int
  2538. #endif
  2539. HINSTANCE hIconvDLL = 0;
  2540. HINSTANCE hMsvcrtDLL = 0;
  2541.  
  2542. #  ifndef DYNAMIC_ICONV_DLL
  2543. #   define DYNAMIC_ICONV_DLL "iconv.dll"
  2544. #  endif
  2545. #  ifndef DYNAMIC_MSVCRT_DLL
  2546. #   define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
  2547. #  endif
  2548.  
  2549. /*
  2550.  * Try opening the iconv.dll and return TRUE if iconv() can be used.
  2551.  */
  2552.     int
  2553. iconv_enabled()
  2554. {
  2555.     if (hIconvDLL != 0 && hMsvcrtDLL != 0)
  2556.     return TRUE;
  2557.     hIconvDLL = LoadLibrary(DYNAMIC_ICONV_DLL);
  2558.     hMsvcrtDLL = LoadLibrary(DYNAMIC_MSVCRT_DLL);
  2559.     if (hIconvDLL == 0 || hMsvcrtDLL == 0)
  2560.     {
  2561.     iconv_end();
  2562.     return FALSE;
  2563.     }
  2564.  
  2565.     *((FARPROC*)&iconv)        = GetProcAddress(hIconvDLL, "libiconv");
  2566.     *((FARPROC*)&iconv_open)    = GetProcAddress(hIconvDLL, "libiconv_open");
  2567.     *((FARPROC*)&iconv_close)    = GetProcAddress(hIconvDLL, "libiconv_close");
  2568.     *((FARPROC*)&iconvctl)    = GetProcAddress(hIconvDLL, "libiconvctl");
  2569.     *((FARPROC*)&iconv_errno)    = GetProcAddress(hMsvcrtDLL, "_errno");
  2570.     if (iconv == NULL || iconv_open == NULL || iconv_close == NULL
  2571.         || iconvctl == NULL || iconv_errno == NULL)
  2572.     {
  2573.     iconv_end();
  2574.     return FALSE;
  2575.     }
  2576.     return TRUE;
  2577. }
  2578.  
  2579.     void
  2580. iconv_end()
  2581. {
  2582.     if (hIconvDLL != 0)
  2583.     FreeLibrary(hIconvDLL);
  2584.     if (hMsvcrtDLL != 0)
  2585.     FreeLibrary(hMsvcrtDLL);
  2586.     hIconvDLL = 0;
  2587.     hMsvcrtDLL = 0;
  2588. }
  2589. #  endif /* DYNAMIC_ICONV */
  2590. # endif /* USE_ICONV */
  2591.  
  2592. #endif /* FEAT_MBYTE */
  2593.  
  2594. #if defined(FEAT_XIM) || defined(PROTO)
  2595.  
  2596. static int    xim_is_active = FALSE;  /* XIM should be active in the current
  2597.                        mode */
  2598. static int    xim_has_focus = FALSE;    /* XIM is really being used for Vim */
  2599. #ifdef FEAT_GUI_X11
  2600. static XIMStyle    input_style;
  2601. static int    status_area_enabled = TRUE;
  2602. #endif
  2603.  
  2604. #if defined(FEAT_GUI_GTK) || defined(PROTO)
  2605. static int    xim_preediting INIT(= FALSE);    /* XIM in showmode() */
  2606. static int    xim_input_style;
  2607. static gboolean    use_status_area = 0;
  2608.  
  2609. static int im_xim_str2keycode __ARGS((unsigned int *code, unsigned int *state));
  2610. static void im_xim_send_event_imactivate __ARGS((void));
  2611.  
  2612. /*
  2613.  * Convert string to keycode and state for XKeyEvent.
  2614.  * When string is valid return OK, when invalid return FAIL.
  2615.  *
  2616.  * See 'imactivatekey' documentation for the format.
  2617.  */
  2618.     static int
  2619. im_xim_str2keycode(code, state)
  2620.     unsigned int *code;
  2621.     unsigned int *state;
  2622. {
  2623.     int        retval = OK;
  2624.     int        len;
  2625.     unsigned    keycode = 0, keystate = 0;
  2626.     Window    window;
  2627.     Display    *display;
  2628.     char_u    *flag_end;
  2629.     char_u    *str;
  2630.  
  2631.     if (*p_imak != NUL)
  2632.     {
  2633.     len = STRLEN(p_imak);
  2634.     for (flag_end = p_imak + len - 1;
  2635.                 flag_end > p_imak && *flag_end != '-'; --flag_end)
  2636.         ;
  2637.  
  2638.     /* Parse modifier keys */
  2639.     for (str = p_imak; str < flag_end; ++str)
  2640.     {
  2641.         switch (*str)
  2642.         {
  2643.         case 's': case 'S':
  2644.             keystate |= ShiftMask;
  2645.             break;
  2646.         case 'l': case 'L':
  2647.             keystate |= LockMask;
  2648.             break;
  2649.         case 'c': case 'C':
  2650.             keystate |= ControlMask;
  2651.             break;
  2652.         case '1':
  2653.             keystate |= Mod1Mask;
  2654.             break;
  2655.         case '2':
  2656.             keystate |= Mod2Mask;
  2657.             break;
  2658.         case '3':
  2659.             keystate |= Mod3Mask;
  2660.             break;
  2661.         case '4':
  2662.             keystate |= Mod4Mask;
  2663.             break;
  2664.         case '5':
  2665.             keystate |= Mod5Mask;
  2666.             break;
  2667.         case '-':
  2668.             break;
  2669.         default:
  2670.             retval = FAIL;
  2671.         }
  2672.     }
  2673.     if (*str == '-')
  2674.         ++str;
  2675.  
  2676.     /* Get keycode from string. */
  2677.     gui_get_x11_windis(&window, &display);
  2678.     if (display)
  2679.         keycode = XKeysymToKeycode(display, XStringToKeysym((char *)str));
  2680.     if (keycode == 0)
  2681.         retval = FAIL;
  2682.  
  2683.     if (code != NULL)
  2684.         *code = keycode;
  2685.     if (state != NULL)
  2686.         *state = keystate;
  2687.     }
  2688.     return retval;
  2689. }
  2690.  
  2691.     static void
  2692. im_xim_send_event_imactivate()
  2693. {
  2694.     /* Force turn on preedit state by symulate keypress event.
  2695.      * Keycode and state is specified by 'imactivatekey'.
  2696.      */
  2697.     XKeyEvent ev;
  2698.  
  2699.     gui_get_x11_windis(&ev.window, &ev.display);
  2700.     ev.root = RootWindow(ev.display, DefaultScreen(ev.display));
  2701.     ev.subwindow = None;
  2702.     ev.time = CurrentTime;
  2703.     ev.x = 1;
  2704.     ev.y = 1;
  2705.     ev.x_root = 1;
  2706.     ev.y_root = 1;
  2707.     ev.same_screen = 1;
  2708.     ev.type = KeyPress;
  2709.     if (im_xim_str2keycode(&ev.keycode, &ev.state) == OK)
  2710.     XSendEvent(ev.display, ev.window, 1, KeyPressMask, (XEvent*)&ev);
  2711. }
  2712.  
  2713. /*
  2714.  * Return TRUE if 'imactivatekey' has a valid value.
  2715.  */
  2716.     int
  2717. im_xim_isvalid_imactivate()
  2718. {
  2719.     return im_xim_str2keycode(NULL, NULL) == OK;
  2720. }
  2721. #endif /* FEAT_GUI_GTK */
  2722.  
  2723. /*
  2724.  * Switch using XIM on/off.  This is used by the code that changes "State".
  2725.  */
  2726.     void
  2727. im_set_active(active)
  2728.     int        active;
  2729. {
  2730.     if (xic == NULL)
  2731.     return;
  2732.  
  2733.     /* If 'imdisable' is set, XIM is never active. */
  2734.     if (p_imdisable)
  2735.     active = FALSE;
  2736. #ifndef FEAT_GUI_GTK
  2737.     else if (input_style & XIMPreeditPosition)
  2738.     /* There is a problem in switching XIM off when preediting is used,
  2739.      * and it is not clear how this can be solved.  For now, keep XIM on
  2740.      * all the time, like it was done in Vim 5.8. */
  2741.     active = TRUE;
  2742. #endif
  2743.  
  2744.     /* Remember the active state, it is needed when Vim gets keyboard focus. */
  2745.     xim_is_active = active;
  2746.  
  2747. #ifdef FEAT_GUI_GTK
  2748.     /* When 'imactivatekey' has valid key-string, try to control XIM preedit
  2749.      * state.  When 'imactivatekey' has no or invalid string, try old XIM
  2750.      * focus control.
  2751.      */
  2752.     if (*p_imak != NUL)
  2753.     {
  2754.     /* BASIC STRATEGY:
  2755.      * Destroy old Input Context (XIC), and create new one.  New XIC
  2756.      * would have a state of preedit that is off.  When argument:active
  2757.      * is false, that's all.  Else argument:active is true, send a key
  2758.      * event specified by 'imactivatekey' to activate XIM preedit state.
  2759.      */
  2760.  
  2761.     xim_is_active = TRUE; /* Disable old XIM focus control */
  2762.     /* If we can monitor preedit state with preedit callback functions,
  2763.      * try least creation of new XIC.
  2764.      */
  2765.     if (xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS)
  2766.     {
  2767.         if (xim_preediting && !active)
  2768.         {
  2769.         /* Force turn off preedit state.  With some IM
  2770.          * implementations, we cannot turn off preedit state by
  2771.          * symulate keypress event.  It is why using such a method
  2772.          * that destroy old IC (input context), and create new one.
  2773.          * When create new IC, its preedit state is usually off.
  2774.          */
  2775.         xim_set_focus(FALSE);
  2776.         gdk_ic_destroy(xic);
  2777.         xim_init();
  2778.         xim_preediting = FALSE;
  2779.         }
  2780.         else if (!xim_preediting && active)
  2781.         im_xim_send_event_imactivate();
  2782.     }
  2783.     else
  2784.     {
  2785.         /* First, force destroy old IC, and create new one.  It
  2786.          * symulates "turning off preedit state".
  2787.          */
  2788.         xim_set_focus(FALSE);
  2789.         gdk_ic_destroy(xic);
  2790.         xim_init();
  2791.         xim_preediting = FALSE;
  2792.  
  2793.         /* 2nd, when requested to activate IM, symulate this by sending
  2794.          * the event.
  2795.          */
  2796.         if (active)
  2797.         {
  2798.         im_xim_send_event_imactivate();
  2799.         xim_preediting = TRUE;
  2800.         }
  2801.     }
  2802.     }
  2803. #else
  2804. # if 0
  2805.     /* When had tested kinput2 + canna + Athena GUI version with
  2806.      * 'imactivatekey' is "s-space", im_xim_send_event_imactivate() did not
  2807.      * work correctly.  It just inserted one space.  I don't know why we
  2808.      * couldn't switch state of XIM preediting.  This is reason why these
  2809.      * codes are commented out.
  2810.      */
  2811.     /* First, force destroy old IC, and create new one.  It symulates
  2812.      * "turning off preedit state".
  2813.      */
  2814.     xim_set_focus(FALSE);
  2815.     XDestroyIC(xic);
  2816.     xic = NULL;
  2817.     xim_init();
  2818.  
  2819.     /* 2nd, when requested to activate IM, symulate this by sending the
  2820.      * event.
  2821.      */
  2822.     if (active)
  2823.         im_xim_send_event_imactivate();
  2824. # endif
  2825. #endif
  2826.     xim_set_preedit();
  2827. }
  2828.  
  2829. /*
  2830.  * Adjust using XIM for gaining or losing keyboard focus.  Also called when
  2831.  * "xim_is_active" changes.
  2832.  */
  2833.     void
  2834. xim_set_focus(focus)
  2835.     int        focus;
  2836. {
  2837.     if (xic == NULL)
  2838.     return;
  2839.  
  2840.     /*
  2841.      * XIM only gets focus when the Vim window has keyboard focus and XIM has
  2842.      * been set active for the current mode.
  2843.      */
  2844.     if (focus && xim_is_active)
  2845.     {
  2846.     if (!xim_has_focus)
  2847.     {
  2848.         xim_has_focus = TRUE;
  2849. #ifdef FEAT_GUI_GTK
  2850.         gdk_im_begin(xic, gui.drawarea->window);
  2851. #else
  2852.         XSetICFocus(xic);
  2853. #endif
  2854.     }
  2855.     }
  2856.     else
  2857.     {
  2858.     if (xim_has_focus)
  2859.     {
  2860.         xim_has_focus = FALSE;
  2861. #ifdef FEAT_GUI_GTK
  2862.         gdk_im_end();
  2863. #else
  2864.         XUnsetICFocus(xic);
  2865. #endif
  2866.     }
  2867.     }
  2868. }
  2869.  
  2870. /*ARGSUSED*/
  2871.     void
  2872. im_set_position(row, col)
  2873.     int        row;
  2874.     int        col;
  2875. {
  2876.     xim_set_preedit();
  2877. }
  2878.  
  2879. /*
  2880.  * Set the XIM to the current cursor position.
  2881.  */
  2882.     void
  2883. xim_set_preedit()
  2884. {
  2885.     if (xic == NULL)
  2886.     return;
  2887.  
  2888.     xim_set_focus(TRUE);
  2889.  
  2890. #ifdef FEAT_GUI_GTK
  2891.     if (gdk_im_ready())
  2892.     {
  2893.     int        attrmask;
  2894.     GdkICAttr    *attr;
  2895.  
  2896.     if (!xic_attr)
  2897.         return;
  2898.  
  2899.     attr = xic_attr;
  2900.     attrmask = 0;
  2901.  
  2902. # ifdef FEAT_XFONTSET
  2903.     if ((xim_input_style & (int)GDK_IM_PREEDIT_POSITION)
  2904.         && gui.fontset != NOFONTSET
  2905.         && gui.fontset->type == GDK_FONT_FONTSET)
  2906.     {
  2907.         if (!xim_has_focus)
  2908.         {
  2909.         if (attr->spot_location.y >= 0)
  2910.         {
  2911.             attr->spot_location.x = 0;
  2912.             attr->spot_location.y = -100;
  2913.             attrmask |= (int)GDK_IC_SPOT_LOCATION;
  2914.         }
  2915.         }
  2916.         else
  2917.         {
  2918.         gint    width, height;
  2919.  
  2920.         if (attr->spot_location.x != TEXT_X(gui.col)
  2921.             || attr->spot_location.y != TEXT_Y(gui.row))
  2922.         {
  2923.             attr->spot_location.x = TEXT_X(gui.col);
  2924.             attr->spot_location.y = TEXT_Y(gui.row);
  2925.             attrmask |= (int)GDK_IC_SPOT_LOCATION;
  2926.         }
  2927.  
  2928.         gdk_window_get_size(gui.drawarea->window, &width, &height);
  2929.         width -= 2 * gui.border_offset;
  2930.         height -= 2 * gui.border_offset;
  2931.         if (xim_input_style & (int)GDK_IM_STATUS_AREA)
  2932.             height -= gui.char_height;
  2933.         if (attr->preedit_area.width != width
  2934.             || attr->preedit_area.height != height)
  2935.         {
  2936.             attr->preedit_area.x = gui.border_offset;
  2937.             attr->preedit_area.y = gui.border_offset;
  2938.             attr->preedit_area.width = width;
  2939.             attr->preedit_area.height = height;
  2940.             attrmask |= (int)GDK_IC_PREEDIT_AREA;
  2941.         }
  2942.  
  2943.         if (attr->preedit_fontset != gui.current_font)
  2944.         {
  2945.             attr->preedit_fontset = gui.current_font;
  2946.             attrmask |= (int)GDK_IC_PREEDIT_FONTSET;
  2947.         }
  2948.         }
  2949.     }
  2950. # endif /* FEAT_XFONTSET */
  2951.  
  2952.     if (xim_fg_color < 0)
  2953.     {
  2954.         xim_fg_color = gui.def_norm_pixel;
  2955.         xim_bg_color = gui.def_back_pixel;
  2956.     }
  2957.     if (attr->preedit_foreground.pixel != xim_fg_color)
  2958.     {
  2959.         attr->preedit_foreground.pixel = xim_fg_color;
  2960.         attrmask |= (int)GDK_IC_PREEDIT_FOREGROUND;
  2961.     }
  2962.     if (attr->preedit_background.pixel != xim_bg_color)
  2963.     {
  2964.         attr->preedit_background.pixel = xim_bg_color;
  2965.         attrmask |= (int)GDK_IC_PREEDIT_BACKGROUND;
  2966.     }
  2967.  
  2968.     if (attrmask != 0)
  2969.         gdk_ic_set_attr(xic, attr, (GdkICAttributesType)attrmask);
  2970.     }
  2971. #else /* FEAT_GUI_GTK */
  2972.     {
  2973.     XVaNestedList attr_list;
  2974.     XRectangle spot_area;
  2975.     XPoint over_spot;
  2976.     int line_space;
  2977.  
  2978.     if (!xim_has_focus)
  2979.     {
  2980.         /* hide XIM cursor */
  2981.         over_spot.x = 0;
  2982.         over_spot.y = -100; /* arbitrary invisible position */
  2983.         attr_list = (XVaNestedList) XVaCreateNestedList(0,
  2984.                                 XNSpotLocation,
  2985.                                 &over_spot,
  2986.                                 NULL);
  2987.         XSetICValues(xic, XNPreeditAttributes, attr_list, NULL);
  2988.         XFree(attr_list);
  2989.         return;
  2990.     }
  2991.  
  2992.     if (input_style & XIMPreeditPosition)
  2993.     {
  2994.         if (xim_fg_color < 0)
  2995.         {
  2996.         xim_fg_color = gui.def_norm_pixel;
  2997.         xim_bg_color = gui.def_back_pixel;
  2998.         }
  2999.         over_spot.x = TEXT_X(gui.col);
  3000.         over_spot.y = TEXT_Y(gui.row);
  3001.         spot_area.x = 0;
  3002.         spot_area.y = 0;
  3003.         spot_area.height = gui.char_height * Rows;
  3004.         spot_area.width  = gui.char_width * Columns;
  3005.         line_space = gui.char_height;
  3006.         attr_list = (XVaNestedList) XVaCreateNestedList(0,
  3007.                         XNSpotLocation, &over_spot,
  3008.                         XNForeground, (Pixel) xim_fg_color,
  3009.                         XNBackground, (Pixel) xim_bg_color,
  3010.                         XNArea, &spot_area,
  3011.                         XNLineSpace, line_space,
  3012.                         NULL);
  3013.         if (XSetICValues(xic, XNPreeditAttributes, attr_list, NULL))
  3014.         EMSG(_("E284: Cannot set IC values"));
  3015.         XFree(attr_list);
  3016.     }
  3017.     }
  3018. #endif /* FEAT_GUI_GTK */
  3019. }
  3020.  
  3021. /*
  3022.  * Set up the status area.
  3023.  *
  3024.  * This should use a separate Widget, but that seems not possible, because
  3025.  * preedit_area and status_area should be set to the same window as for the
  3026.  * text input.  Unfortunately this means the status area pollutes the text
  3027.  * window...
  3028.  */
  3029.     void
  3030. xim_set_status_area()
  3031. {
  3032.     if (xic == NULL)
  3033.     return;
  3034.  
  3035. #ifdef FEAT_GUI_GTK
  3036. # if defined(FEAT_XFONTSET)
  3037.     if (use_status_area)
  3038.     {
  3039.     GdkICAttr    *attr;
  3040.     int        style;
  3041.     gint        width, height;
  3042.     GtkWidget    *widget;
  3043.     int        attrmask;
  3044.  
  3045.     if (!xic_attr)
  3046.         return;
  3047.  
  3048.     attr = xic_attr;
  3049.     attrmask = 0;
  3050.     style = (int)gdk_ic_get_style(xic);
  3051.     if ((style & (int)GDK_IM_STATUS_MASK) == (int)GDK_IM_STATUS_AREA)
  3052.     {
  3053.         if (gui.fontset != NOFONTSET
  3054.             && gui.fontset->type == GDK_FONT_FONTSET)
  3055.         {
  3056.         widget = gui.mainwin;
  3057.         gdk_window_get_size(widget->window, &width, &height);
  3058.  
  3059.         attrmask |= (int)GDK_IC_STATUS_AREA;
  3060.         attr->status_area.x = 0;
  3061.         attr->status_area.y = height - gui.char_height - 1;
  3062.         attr->status_area.width = width;
  3063.         attr->status_area.height = gui.char_height;
  3064.         }
  3065.     }
  3066.     if (attrmask != 0)
  3067.         gdk_ic_set_attr(xic, attr, (GdkICAttributesType)attrmask);
  3068.     }
  3069. # endif
  3070. #else
  3071.     {
  3072.     XVaNestedList preedit_list = 0, status_list = 0, list = 0;
  3073.     XRectangle pre_area, status_area;
  3074.  
  3075.     if (input_style & XIMStatusArea)
  3076.     {
  3077.         if (input_style & XIMPreeditArea)
  3078.         {
  3079.         XRectangle *needed_rect;
  3080.  
  3081.         /* to get status_area width */
  3082.         status_list = XVaCreateNestedList(0, XNAreaNeeded,
  3083.                           &needed_rect, NULL);
  3084.         XGetICValues(xic, XNStatusAttributes, status_list, NULL);
  3085.         XFree(status_list);
  3086.  
  3087.         status_area.width = needed_rect->width;
  3088.         }
  3089.         else
  3090.         status_area.width = gui.char_width * Columns;
  3091.  
  3092.         status_area.x = 0;
  3093.         status_area.y = gui.char_height * Rows + gui.border_offset;
  3094.         if (gui.which_scrollbars[SBAR_BOTTOM])
  3095.         status_area.y += gui.scrollbar_height;
  3096. #ifdef FEAT_MENU
  3097.         if (gui.menu_is_active)
  3098.         status_area.y += gui.menu_height;
  3099. #endif
  3100.         status_area.height = gui.char_height;
  3101.         status_list = XVaCreateNestedList(0, XNArea, &status_area, NULL);
  3102.     }
  3103.     else
  3104.     {
  3105.         status_area.x = 0;
  3106.         status_area.y = gui.char_height * Rows + gui.border_offset;
  3107.         if (gui.which_scrollbars[SBAR_BOTTOM])
  3108.         status_area.y += gui.scrollbar_height;
  3109. #ifdef FEAT_MENU
  3110.         if (gui.menu_is_active)
  3111.         status_area.y += gui.menu_height;
  3112. #endif
  3113.         status_area.width = 0;
  3114.         status_area.height = gui.char_height;
  3115.     }
  3116.  
  3117.     if (input_style & XIMPreeditArea)   /* off-the-spot */
  3118.     {
  3119.         pre_area.x = status_area.x + status_area.width;
  3120.         pre_area.y = gui.char_height * Rows + gui.border_offset;
  3121.         pre_area.width = gui.char_width * Columns - pre_area.x;
  3122.         if (gui.which_scrollbars[SBAR_BOTTOM])
  3123.         pre_area.y += gui.scrollbar_height;
  3124. #ifdef FEAT_MENU
  3125.         if (gui.menu_is_active)
  3126.         pre_area.y += gui.menu_height;
  3127. #endif
  3128.         pre_area.height = gui.char_height;
  3129.         preedit_list = XVaCreateNestedList(0, XNArea, &pre_area, NULL);
  3130.     }
  3131.     else if (input_style & XIMPreeditPosition)   /* over-the-spot */
  3132.     {
  3133.         pre_area.x = 0;
  3134.         pre_area.y = 0;
  3135.         pre_area.height = gui.char_height * Rows;
  3136.         pre_area.width = gui.char_width * Columns;
  3137.         preedit_list = XVaCreateNestedList(0, XNArea, &pre_area, NULL);
  3138.     }
  3139.  
  3140.     if (preedit_list && status_list)
  3141.         list = XVaCreateNestedList(0, XNPreeditAttributes, preedit_list,
  3142.                        XNStatusAttributes, status_list, NULL);
  3143.     else if (preedit_list)
  3144.         list = XVaCreateNestedList(0, XNPreeditAttributes, preedit_list,
  3145.                        NULL);
  3146.     else if (status_list)
  3147.         list = XVaCreateNestedList(0, XNStatusAttributes, status_list,
  3148.                        NULL);
  3149.     else
  3150.         list = NULL;
  3151.  
  3152.     if (list)
  3153.     {
  3154.         XSetICValues(xic, XNVaNestedList, list, NULL);
  3155.         XFree(list);
  3156.     }
  3157.     if (status_list)
  3158.         XFree(status_list);
  3159.     if (preedit_list)
  3160.         XFree(preedit_list);
  3161.     }
  3162. #endif
  3163. }
  3164.  
  3165. #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
  3166. static char e_xim[] = N_("E285: Failed to create input context");
  3167. #endif
  3168.  
  3169. #if defined(FEAT_GUI_X11) || defined(PROTO)
  3170. # if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && !defined(sun)
  3171. #  define USE_X11R6_XIM
  3172. # endif
  3173.  
  3174. static int xim_real_init __ARGS((Window x11_window, Display *x11_display));
  3175.  
  3176.  
  3177. #ifdef USE_X11R6_XIM
  3178. static void xim_instantiate_cb __ARGS((Display *display, XPointer client_data, XPointer    call_data));
  3179. static void xim_destroy_cb __ARGS((XIM im, XPointer client_data, XPointer call_data));
  3180.  
  3181. /*ARGSUSED*/
  3182.     static void
  3183. xim_instantiate_cb(display, client_data, call_data)
  3184.     Display    *display;
  3185.     XPointer    client_data;
  3186.     XPointer    call_data;
  3187. {
  3188.     Window    x11_window;
  3189.     Display    *x11_display;
  3190.  
  3191.     gui_get_x11_windis(&x11_window, &x11_display);
  3192.     if (display != x11_display)
  3193.     return;
  3194.  
  3195.     xim_real_init(x11_window, x11_display);
  3196.     gui_set_shellsize(FALSE, FALSE);
  3197.     if (xic != NULL)
  3198.     XUnregisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
  3199.                      xim_instantiate_cb, NULL);
  3200. }
  3201.  
  3202. /*ARGSUSED*/
  3203.     static void
  3204. xim_destroy_cb(im, client_data, call_data)
  3205.     XIM        im;
  3206.     XPointer    client_data;
  3207.     XPointer    call_data;
  3208. {
  3209.     Window    x11_window;
  3210.     Display    *x11_display;
  3211.  
  3212.     gui_get_x11_windis(&x11_window, &x11_display);
  3213.  
  3214.     xic = NULL;
  3215.     status_area_enabled = FALSE;
  3216.  
  3217.     gui_set_shellsize(FALSE, FALSE);
  3218.  
  3219.     XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
  3220.                    xim_instantiate_cb, NULL);
  3221. }
  3222. #endif
  3223.  
  3224.     void
  3225. xim_init()
  3226. {
  3227.     Window    x11_window;
  3228.     Display    *x11_display;
  3229.  
  3230.     gui_get_x11_windis(&x11_window, &x11_display);
  3231.  
  3232.     xic = NULL;
  3233.  
  3234.     if (xim_real_init(x11_window, x11_display))
  3235.     return;
  3236.  
  3237.     gui_set_shellsize(FALSE, FALSE);
  3238.  
  3239. #ifdef USE_X11R6_XIM
  3240.     XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
  3241.                    xim_instantiate_cb, NULL);
  3242. #endif
  3243. }
  3244.  
  3245.     static int
  3246. xim_real_init(x11_window, x11_display)
  3247.     Window    x11_window;
  3248.     Display    *x11_display;
  3249. {
  3250.     int        i;
  3251.     char    *p,
  3252.         *s,
  3253.         *ns,
  3254.         *end,
  3255.         tmp[1024];
  3256. #define IMLEN_MAX 40
  3257.     char    buf[IMLEN_MAX + 7];
  3258.     XIM        xim = NULL;
  3259.     XIMStyles    *xim_styles;
  3260.     XIMStyle    this_input_style = 0;
  3261.     Boolean    found;
  3262.     XPoint    over_spot;
  3263.     XVaNestedList preedit_list, status_list;
  3264.  
  3265.     input_style = 0;
  3266.     status_area_enabled = FALSE;
  3267.  
  3268.     if (xic != NULL)
  3269.     return FALSE;
  3270.  
  3271.     if (gui.rsrc_input_method != NULL && *gui.rsrc_input_method != NUL)
  3272.     {
  3273.     strcpy(tmp, gui.rsrc_input_method);
  3274.     for (ns = s = tmp; ns != NULL && *s != NUL;)
  3275.     {
  3276.         s = (char *)skipwhite((char_u *)s);
  3277.         if (*s == NUL)
  3278.         break;
  3279.         if ((ns = end = strchr(s, ',')) == NULL)
  3280.         end = s + strlen(s);
  3281.         while (isspace(((char_u *)end)[-1]))
  3282.         end--;
  3283.         *end = NUL;
  3284.  
  3285.         if (strlen(s) <= IMLEN_MAX)
  3286.         {
  3287.         strcpy(buf, "@im=");
  3288.         strcat(buf, s);
  3289.         if ((p = XSetLocaleModifiers(buf)) != NULL && *p != NUL
  3290.             && (xim = XOpenIM(x11_display, NULL, NULL, NULL))
  3291.                                       != NULL)
  3292.             break;
  3293.         }
  3294.  
  3295.         s = ns + 1;
  3296.     }
  3297.     }
  3298.  
  3299.     if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p != NUL)
  3300.     xim = XOpenIM(x11_display, NULL, NULL, NULL);
  3301.  
  3302.     /* This is supposed to be useful to obtain characters through
  3303.      * XmbLookupString() without really using a XIM. */
  3304.     if (xim == NULL && (p = XSetLocaleModifiers("@im=none")) != NULL
  3305.                                  && *p != NUL)
  3306.     xim = XOpenIM(x11_display, NULL, NULL, NULL);
  3307.  
  3308.     if (xim == NULL)
  3309.     {
  3310.     /* Only give this message when verbose is set, because too many people
  3311.      * got this message when they didn't want to use a XIM. */
  3312.     if (p_verbose > 0)
  3313.         EMSG(_("E286: Failed to open input method"));
  3314.     return FALSE;
  3315.     }
  3316.  
  3317. #ifdef USE_X11R6_XIM
  3318.     {
  3319.     XIMCallback destroy_cb;
  3320.  
  3321.     destroy_cb.callback = xim_destroy_cb;
  3322.     destroy_cb.client_data = NULL;
  3323.     if (XSetIMValues(xim, XNDestroyCallback, &destroy_cb, NULL))
  3324.         EMSG(_("E287: Warning: Could not set destroy callback to IM"));
  3325.     }
  3326. #endif
  3327.  
  3328.     if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles)
  3329.     {
  3330.     EMSG(_("E288: input method doesn't support any style"));
  3331.     XCloseIM(xim);
  3332.     return FALSE;
  3333.     }
  3334.  
  3335.     found = False;
  3336.     strcpy(tmp, gui.rsrc_preedit_type_name);
  3337.     for (s = tmp; s && !found; )
  3338.     {
  3339.     while (*s && isspace((unsigned char)*s))
  3340.         s++;
  3341.     if (!*s)
  3342.         break;
  3343.     if ((ns = end = strchr(s, ',')) != 0)
  3344.         ns++;
  3345.     else
  3346.         end = s + strlen(s);
  3347.     while (isspace((unsigned char)*end))
  3348.         end--;
  3349.     *end = '\0';
  3350.  
  3351.     if (!strcmp(s, "OverTheSpot"))
  3352.         this_input_style = (XIMPreeditPosition | XIMStatusArea);
  3353.     else if (!strcmp(s, "OffTheSpot"))
  3354.         this_input_style = (XIMPreeditArea | XIMStatusArea);
  3355.     else if (!strcmp(s, "Root"))
  3356.         this_input_style = (XIMPreeditNothing | XIMStatusNothing);
  3357.  
  3358.     for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
  3359.     {
  3360.         if (this_input_style == xim_styles->supported_styles[i])
  3361.         {
  3362.         found = True;
  3363.         break;
  3364.         }
  3365.     }
  3366.     if (!found)
  3367.         for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
  3368.         {
  3369.         if ((xim_styles->supported_styles[i] & this_input_style)
  3370.             == (this_input_style & ~XIMStatusArea))
  3371.         {
  3372.             this_input_style &= ~XIMStatusArea;
  3373.             found = True;
  3374.             break;
  3375.         }
  3376.         }
  3377.  
  3378.     s = ns;
  3379.     }
  3380.     XFree(xim_styles);
  3381.  
  3382.     if (!found)
  3383.     {
  3384.     /* Only give this message when verbose is set, because too many people
  3385.      * got this message when they didn't want to use a XIM. */
  3386.     if (p_verbose > 0)
  3387.         EMSG(_("E289: input method doesn't support my preedit type"));
  3388.     XCloseIM(xim);
  3389.     return FALSE;
  3390.     }
  3391.  
  3392.     over_spot.x = TEXT_X(gui.col);
  3393.     over_spot.y = TEXT_Y(gui.row);
  3394.     input_style = this_input_style;
  3395.  
  3396.     /* A crash was reported when trying to pass gui.norm_font as XNFontSet,
  3397.      * thus that has been removed.  Hopefully the default works... */
  3398. #ifdef FEAT_XFONTSET
  3399.     if (gui.fontset != NOFONTSET)
  3400.     {
  3401.     preedit_list = XVaCreateNestedList(0,
  3402.                 XNSpotLocation, &over_spot,
  3403.                 XNForeground, (Pixel)gui.def_norm_pixel,
  3404.                 XNBackground, (Pixel)gui.def_back_pixel,
  3405.                 XNFontSet, (XFontSet)gui.fontset,
  3406.                 NULL);
  3407.     status_list = XVaCreateNestedList(0,
  3408.                 XNForeground, (Pixel)gui.def_norm_pixel,
  3409.                 XNBackground, (Pixel)gui.def_back_pixel,
  3410.                 XNFontSet, (XFontSet)gui.fontset,
  3411.                 NULL);
  3412.     }
  3413.     else
  3414. #endif
  3415.     {
  3416.     preedit_list = XVaCreateNestedList(0,
  3417.                 XNSpotLocation, &over_spot,
  3418.                 XNForeground, (Pixel)gui.def_norm_pixel,
  3419.                 XNBackground, (Pixel)gui.def_back_pixel,
  3420.                 NULL);
  3421.     status_list = XVaCreateNestedList(0,
  3422.                 XNForeground, (Pixel)gui.def_norm_pixel,
  3423.                 XNBackground, (Pixel)gui.def_back_pixel,
  3424.                 NULL);
  3425.     }
  3426.  
  3427.     xic = XCreateIC(xim,
  3428.             XNInputStyle, input_style,
  3429.             XNClientWindow, x11_window,
  3430.             XNFocusWindow, gui.wid,
  3431.             XNPreeditAttributes, preedit_list,
  3432.             XNStatusAttributes, status_list,
  3433.             NULL);
  3434.     XFree(status_list);
  3435.     XFree(preedit_list);
  3436.     if (xic != NULL)
  3437.     {
  3438.     if (input_style & XIMStatusArea)
  3439.     {
  3440.         xim_set_status_area();
  3441.         status_area_enabled = TRUE;
  3442.     }
  3443.     else
  3444.         gui_set_shellsize(FALSE, FALSE);
  3445.     }
  3446.     else
  3447.     {
  3448.     EMSG(_(e_xim));
  3449.     XCloseIM(xim);
  3450.     return FALSE;
  3451.     }
  3452.  
  3453.     return TRUE;
  3454. }
  3455.  
  3456. #endif /* FEAT_GUI_X11 */
  3457.  
  3458. #if defined(FEAT_GUI_GTK) || defined(PROTO)
  3459.  
  3460. # ifdef FEAT_XFONTSET
  3461. static char e_overthespot[] = N_("E290: over-the-spot style requires fontset");
  3462. # endif
  3463.  
  3464. void
  3465. xim_decide_input_style()
  3466. {
  3467.     /* GDK_IM_STATUS_CALLBACKS was disabled, enabled it to allow Japanese
  3468.      * OverTheSpot. */
  3469.     int supported_style = (int)GDK_IM_PREEDIT_NONE |
  3470.                  (int)GDK_IM_PREEDIT_NOTHING |
  3471.                  (int)GDK_IM_PREEDIT_POSITION |
  3472.                  (int)GDK_IM_PREEDIT_CALLBACKS |
  3473.                  (int)GDK_IM_STATUS_CALLBACKS |
  3474.                  (int)GDK_IM_STATUS_AREA |
  3475.                  (int)GDK_IM_STATUS_NONE |
  3476.                  (int)GDK_IM_STATUS_NOTHING;
  3477.  
  3478.     if (!gdk_im_ready())
  3479.     xim_input_style = 0;
  3480.     else
  3481.     {
  3482.     if (gtk_major_version > 1
  3483.         || (gtk_major_version == 1
  3484.             && (gtk_minor_version > 2
  3485.             || (gtk_minor_version == 2 && gtk_micro_version >= 3))))
  3486.         use_status_area = TRUE;
  3487.     else
  3488.     {
  3489.         EMSG(_("E291: Your GTK+ is older than 1.2.3. Status area disabled"));
  3490.         use_status_area = FALSE;
  3491.     }
  3492. #ifdef FEAT_XFONTSET
  3493.     if (gui.fontset == NOFONTSET || gui.fontset->type != GDK_FONT_FONTSET)
  3494. #endif
  3495.         supported_style &= ~((int)GDK_IM_PREEDIT_POSITION
  3496.                            | (int)GDK_IM_STATUS_AREA);
  3497.     if (!use_status_area)
  3498.         supported_style &= ~(int)GDK_IM_STATUS_AREA;
  3499.     xim_input_style = (int)gdk_im_decide_style((GdkIMStyle)supported_style);
  3500.     }
  3501. }
  3502.  
  3503. #ifdef FEAT_GUI_GTK
  3504. # include <gdk/gdkx.h>
  3505. #else
  3506. /* Define a few things to be able to generate prototypes while not configured
  3507.  * for GTK. */
  3508. # define GSList int
  3509. # define gboolean int
  3510.   typedef int GdkEvent;
  3511. # define GdkIC int
  3512. #endif
  3513.  
  3514. /*ARGSUSED*/
  3515.     static void
  3516. preedit_start_cbproc(XIC xic, XPointer client_data, XPointer call_data)
  3517. {
  3518.     xim_preediting = TRUE;
  3519.     gui_update_cursor(TRUE, FALSE);
  3520.     if (showmode() > 0)
  3521.     {
  3522.     setcursor();
  3523.     out_flush();
  3524.     }
  3525. }
  3526.  
  3527.     static void
  3528. xim_back_delete(int n)
  3529. {
  3530.     char_u str[3];
  3531.  
  3532.     str[0] = CSI;
  3533.     str[1] = 'k';
  3534.     str[2] = 'b';
  3535.     while (n-- > 0)
  3536.     add_to_input_buf(str, 3);
  3537. }
  3538.  
  3539. /*
  3540.  * Add "str[len]" to the input buffer while escaping CSI bytes.
  3541.  */
  3542.     static void
  3543. add_to_input_buf_csi(char_u *str, int len)
  3544. {
  3545.     int        i;
  3546.     char_u    buf[2];
  3547.  
  3548.     for (i = 0; i < len; ++i)
  3549.     {
  3550.     add_to_input_buf(str + i, 1);
  3551.     if (str[i] == CSI)
  3552.     {
  3553.         /* Turn CSI into K_CSI. */
  3554.         buf[0] = KS_EXTRA;
  3555.         buf[1] = (int)KE_CSI;
  3556.         add_to_input_buf(buf, 2);
  3557.     }
  3558.     }
  3559. }
  3560.  
  3561. static GSList *key_press_event_queue = NULL;
  3562. static int preedit_buf_len = 0;
  3563. static gboolean processing_queued_event = FALSE;
  3564.  
  3565. /*ARGSUSED*/
  3566.     static void
  3567. preedit_draw_cbproc(XIC xic, XPointer client_data, XPointer call_data)
  3568. {
  3569.     XIMPreeditDrawCallbackStruct *draw_data;
  3570.     XIMText    *text;
  3571.     char    *src;
  3572.     GSList    *event_queue;
  3573.  
  3574.     draw_data = (XIMPreeditDrawCallbackStruct *) call_data;
  3575.     text = (XIMText *) draw_data->text;
  3576.  
  3577.     if (draw_data->chg_length > 0)
  3578.     {
  3579.     int bs_cnt;
  3580.  
  3581.     if (draw_data->chg_length > preedit_buf_len)
  3582.         bs_cnt = preedit_buf_len;
  3583.     else
  3584.         bs_cnt = draw_data->chg_length;
  3585.     xim_back_delete(bs_cnt);
  3586.     preedit_buf_len -= bs_cnt;
  3587.     }
  3588.     if (text != NULL && (src = text->string.multi_byte) != NULL)
  3589.     {
  3590.     int        len = strlen(src);
  3591. #ifdef FEAT_MBYTE
  3592.     char_u        *buf;
  3593. #endif
  3594.     GdkWChar    *wstr = NULL;
  3595.  
  3596.     wstr = g_new(GdkWChar, len);
  3597.     preedit_buf_len += gdk_mbstowcs(wstr, src, len);
  3598.     g_free(wstr);
  3599. #ifdef FEAT_MBYTE
  3600.     if (input_conv.vc_type != CONV_NONE
  3601.         && (buf = string_convert(&input_conv,
  3602.                          (char_u *)src, &len)) != NULL)
  3603.     {
  3604.         /* Converted from 'termencoding' to 'encoding'. */
  3605.         add_to_input_buf_csi(buf, len);
  3606.         vim_free(buf);
  3607.     }
  3608.     else
  3609. #endif
  3610.         add_to_input_buf_csi((char_u *)src, len);
  3611.     }
  3612.     event_queue = key_press_event_queue;
  3613.     processing_queued_event = TRUE;
  3614.     while (event_queue)
  3615.     {
  3616.     GdkEvent *ev = event_queue->data;
  3617.     gboolean *ret;
  3618.     gtk_signal_emit_by_name((GtkObject*)gui.mainwin, "key_press_event",
  3619.                 ev, &ret);
  3620.     gdk_event_free(ev);
  3621.     event_queue = event_queue->next;
  3622.     }
  3623.     processing_queued_event = FALSE;
  3624.     if (key_press_event_queue)
  3625.     {
  3626.     g_slist_free(key_press_event_queue);
  3627.     key_press_event_queue = NULL;
  3628.     }
  3629.     if (gtk_main_level() > 0)
  3630.     gtk_main_quit();
  3631. }
  3632.  
  3633. /*ARGSUSED*/
  3634.     static void
  3635. preedit_caret_cbproc(XIC xic, XPointer client_data, XPointer call_data)
  3636. {
  3637. }
  3638.  
  3639. /*ARGSUSED*/
  3640.     static void
  3641. preedit_done_cbproc(XIC xic, XPointer client_data, XPointer call_data)
  3642. {
  3643.     xim_preediting = FALSE;
  3644.     gui_update_cursor(TRUE, FALSE);
  3645.     if (showmode() > 0)
  3646.     {
  3647.     setcursor();
  3648.     out_flush();
  3649.     }
  3650. }
  3651.  
  3652.     void
  3653. xim_reset(void)
  3654. {
  3655.     char *text;
  3656.  
  3657.     if (xic != NULL)
  3658.     {
  3659.     text = XmbResetIC(((GdkICPrivate *)xic)->xic);
  3660.     if (text != NULL && !(xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS))
  3661.         add_to_input_buf_csi((char_u *)text, strlen(text));
  3662.     else
  3663.         preedit_buf_len = 0;
  3664.     if (text != NULL)
  3665.         XFree(text);
  3666.     }
  3667. }
  3668.  
  3669.     int
  3670. xim_queue_key_press_event(GdkEvent *ev)
  3671. {
  3672.     if (preedit_buf_len <= 0 || processing_queued_event)
  3673.     return FALSE;
  3674.  
  3675.     key_press_event_queue = g_slist_append(key_press_event_queue,
  3676.                        gdk_event_copy(ev));
  3677.     return TRUE;
  3678. }
  3679.  
  3680. /*ARGSUSED*/
  3681.     static void
  3682. preedit_callback_setup(GdkIC *ic)
  3683. {
  3684.     XIC xxic;
  3685.     XVaNestedList preedit_attr;
  3686.     XIMCallback preedit_start_cb;
  3687.     XIMCallback preedit_draw_cb;
  3688.     XIMCallback preedit_caret_cb;
  3689.     XIMCallback preedit_done_cb;
  3690.  
  3691.     xxic = ((GdkICPrivate*)xic)->xic;
  3692.     preedit_start_cb.callback = (XIMProc)preedit_start_cbproc;
  3693.     preedit_draw_cb.callback = (XIMProc)preedit_draw_cbproc;
  3694.     preedit_caret_cb.callback = (XIMProc)preedit_caret_cbproc;
  3695.     preedit_done_cb.callback = (XIMProc)preedit_done_cbproc;
  3696.     preedit_attr
  3697.     = XVaCreateNestedList (0,
  3698.                    XNPreeditStartCallback, &preedit_start_cb,
  3699.                    XNPreeditDrawCallback, &preedit_draw_cb,
  3700.                    XNPreeditCaretCallback, &preedit_caret_cb,
  3701.                    XNPreeditDoneCallback, &preedit_done_cb,
  3702.                    0);
  3703.     XSetICValues (xxic, XNPreeditAttributes, preedit_attr, 0);
  3704.     XFree(preedit_attr);
  3705. }
  3706.  
  3707. /*ARGSUSED*/
  3708.     static void
  3709. reset_state_setup(GdkIC *ic)
  3710. {
  3711. #ifdef USE_X11R6_XIM
  3712.     /* don't change the input context when we call reset */
  3713.     XSetICValues(((GdkICPrivate*)ic)->xic, XNResetState, XIMPreserveState, 0);
  3714. #endif
  3715. }
  3716.  
  3717.     void
  3718. xim_init(void)
  3719. {
  3720.     xic = NULL;
  3721.     xic_attr = NULL;
  3722.  
  3723.     if (!gdk_im_ready())
  3724.     {
  3725.     if (p_verbose > 0)
  3726.         EMSG(_("E292: Input Method Server is not running"));
  3727.     return;
  3728.     }
  3729.     if ((xic_attr = gdk_ic_attr_new()) != NULL)
  3730.     {
  3731. #ifdef FEAT_XFONTSET
  3732.     gint width, height;
  3733. #endif
  3734.     int        mask;
  3735.     GdkColormap    *colormap;
  3736.     GdkICAttr    *attr = xic_attr;
  3737.     int        attrmask = (int)GDK_IC_ALL_REQ;
  3738.     GtkWidget    *widget = gui.drawarea;
  3739.  
  3740.     attr->style = (GdkIMStyle)xim_input_style;
  3741.     attr->client_window = gui.mainwin->window;
  3742.  
  3743.     if ((colormap = gtk_widget_get_colormap(widget)) !=
  3744.         gtk_widget_get_default_colormap())
  3745.     {
  3746.         attrmask |= (int)GDK_IC_PREEDIT_COLORMAP;
  3747.         attr->preedit_colormap = colormap;
  3748.     }
  3749.     attrmask |= (int)GDK_IC_PREEDIT_FOREGROUND;
  3750.     attrmask |= (int)GDK_IC_PREEDIT_BACKGROUND;
  3751.     attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
  3752.     attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
  3753.  
  3754. #ifdef FEAT_XFONTSET
  3755.     if ((xim_input_style & (int)GDK_IM_PREEDIT_MASK)
  3756.                           == (int)GDK_IM_PREEDIT_POSITION)
  3757.     {
  3758.         if (gui.fontset == NOFONTSET
  3759.             || gui.fontset->type != GDK_FONT_FONTSET)
  3760.         {
  3761.         EMSG(_(e_overthespot));
  3762.         }
  3763.         else
  3764.         {
  3765.         gdk_window_get_size(widget->window, &width, &height);
  3766.  
  3767.         attrmask |= (int)GDK_IC_PREEDIT_POSITION_REQ;
  3768.         attr->spot_location.x = TEXT_X(0);
  3769.         attr->spot_location.y = TEXT_Y(0);
  3770.         attr->preedit_area.x = gui.border_offset;
  3771.         attr->preedit_area.y = gui.border_offset;
  3772.         attr->preedit_area.width = width - 2*gui.border_offset;
  3773.         attr->preedit_area.height = height - 2*gui.border_offset;
  3774.         attr->preedit_fontset = gui.fontset;
  3775.         }
  3776.     }
  3777.  
  3778.     if ((xim_input_style & (int)GDK_IM_STATUS_MASK)
  3779.                            == (int)GDK_IM_STATUS_AREA)
  3780.     {
  3781.         if (gui.fontset == NOFONTSET
  3782.             || gui.fontset->type != GDK_FONT_FONTSET)
  3783.         {
  3784.         EMSG(_(e_overthespot));
  3785.         }
  3786.         else
  3787.         {
  3788.         gdk_window_get_size(gui.mainwin->window, &width, &height);
  3789.         attrmask |= (int)GDK_IC_STATUS_AREA_REQ;
  3790.         attr->status_area.x = 0;
  3791.         attr->status_area.y = height - gui.char_height - 1;
  3792.         attr->status_area.width = width;
  3793.         attr->status_area.height = gui.char_height;
  3794.         attr->status_fontset = gui.fontset;
  3795.         }
  3796.     }
  3797.     else if ((xim_input_style & (int)GDK_IM_STATUS_MASK)
  3798.                           == (int)GDK_IM_STATUS_CALLBACKS)
  3799.     {
  3800.         /* FIXME */
  3801.     }
  3802. #endif
  3803.  
  3804.     xic = gdk_ic_new(attr, (GdkICAttributesType)attrmask);
  3805.  
  3806.     if (xic == NULL)
  3807.         EMSG(_(e_xim));
  3808.     else
  3809.     {
  3810.         mask = (int)gdk_window_get_events(widget->window);
  3811.         mask |= (int)gdk_ic_get_events(xic);
  3812.         gdk_window_set_events(widget->window, (GdkEventMask)mask);
  3813.         if (xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS)
  3814.         preedit_callback_setup(xic);
  3815.         reset_state_setup(xic);
  3816.     }
  3817.     }
  3818. }
  3819. #endif /* FEAT_GUI_GTK */
  3820.  
  3821.     int
  3822. xim_get_status_area_height()
  3823. {
  3824. #ifdef FEAT_GUI_GTK
  3825.     if (xim_input_style & (int)GDK_IM_STATUS_AREA)
  3826.     return gui.char_height;
  3827. #else
  3828.     if (status_area_enabled)
  3829.     return gui.char_height;
  3830. #endif
  3831.     return 0;
  3832. }
  3833.  
  3834. /*
  3835.  * Get IM status.  When IM is on, return TRUE.  Else return FALSE.
  3836.  * FIXME: This doesn't work correctly: Having focus doesn't always mean XIM is
  3837.  * active, when not having focus XIM may still be active (e.g., when using a
  3838.  * tear-off menu item).
  3839.  */
  3840.     int
  3841. im_get_status()
  3842. {
  3843. #ifdef FEAT_GUI_GTK
  3844.     if (xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS)
  3845.     return xim_preediting;
  3846. #endif
  3847.     return xim_has_focus;
  3848. }
  3849.  
  3850. #endif /* FEAT_XIM */
  3851.  
  3852. #if defined(FEAT_MBYTE) || defined(PROTO)
  3853.  
  3854. /*
  3855.  * Setup "vcp" for conversion from "from" to "to".
  3856.  * The names must have been made canonical with enc_canonize().
  3857.  * Note: cannot be used for conversion from/to ucs-2 and ucs-4 (will use utf-8
  3858.  * instead).
  3859.  */
  3860.     void
  3861. convert_setup(vcp, from, to)
  3862.     vimconv_T    *vcp;
  3863.     char_u    *from;
  3864.     char_u    *to;
  3865. {
  3866.     int        from_prop;
  3867.     int        to_prop;
  3868.  
  3869.     /* Reset to no conversion. */
  3870.     vcp->vc_type = CONV_NONE;
  3871.     vcp->vc_factor = 1;
  3872. # ifdef USE_ICONV
  3873.     if (vcp->vc_fd != (iconv_t)-1)
  3874.     {
  3875.     iconv_close(vcp->vc_fd);
  3876.     vcp->vc_fd = (iconv_t)-1;
  3877.     }
  3878. # endif
  3879.  
  3880.     /* No conversion when one of the names is empty or they are equal. */
  3881.     if (*from == NUL || *to == NUL || STRCMP(from, to) == 0)
  3882.     return;
  3883.  
  3884.     from_prop = enc_canon_props(from);
  3885.     to_prop = enc_canon_props(to);
  3886.     if ((from_prop & ENC_LATIN1) && (to_prop & ENC_UNICODE))
  3887.     {
  3888.     /* Internal latin1 -> utf-8 conversion. */
  3889.     vcp->vc_type = CONV_TO_UTF8;
  3890.     vcp->vc_factor = 2;    /* up to twice as long */
  3891.     }
  3892.     else if ((from_prop & ENC_UNICODE) && (to_prop & ENC_LATIN1))
  3893.     {
  3894.     /* Internal utf-8 -> latin1 conversion. */
  3895.     vcp->vc_type = CONV_TO_LATIN1;
  3896.     }
  3897. # ifdef USE_ICONV
  3898.     else
  3899.     {
  3900.     /* Use iconv() for conversion. */
  3901.     vcp->vc_fd = (iconv_t)my_iconv_open(
  3902.         (to_prop & ENC_UNICODE) ? (char_u *)"utf-8" : to,
  3903.         (from_prop & ENC_UNICODE) ? (char_u *)"utf-8" : from);
  3904.     if (vcp->vc_fd != (iconv_t)-1)
  3905.     {
  3906.         vcp->vc_type = CONV_ICONV;
  3907.         vcp->vc_factor = 4;    /* could be longer too... */
  3908.     }
  3909.     }
  3910. # endif
  3911. }
  3912.  
  3913. /*
  3914.  * Do conversion on typed input characters in-place.
  3915.  * Returns the length after conversion.
  3916.  */
  3917.     int
  3918. convert_input(ptr, len, maxlen)
  3919.     char_u    *ptr;
  3920.     int        len;
  3921.     int        maxlen;
  3922. {
  3923.     char_u    *d;
  3924.     int        l;
  3925.  
  3926.     d = string_convert(&input_conv, ptr, &len);
  3927.     if (d != NULL)
  3928.     {
  3929.     l = (int)STRLEN(d);
  3930.     if (l <= maxlen)
  3931.     {
  3932.         mch_memmove(ptr, d, l);
  3933.         len = l;
  3934.     }
  3935.     vim_free(d);
  3936.     }
  3937.     return len;
  3938. }
  3939.  
  3940. /*
  3941.  * Convert text "ptr[*lenp]" according to "vcp".
  3942.  * Returns the result in allocated memory and sets "*lenp".
  3943.  * When "lenp" is NULL, use NUL terminated strings.
  3944.  * When something goes wrong, NULL is returned.
  3945.  */
  3946.     char_u *
  3947. string_convert(vcp, ptr, lenp)
  3948.     vimconv_T    *vcp;
  3949.     char_u    *ptr;
  3950.     int        *lenp;
  3951. {
  3952.     char_u    *retval = NULL;
  3953.     char_u    *d;
  3954.     int        len;
  3955.     int        i;
  3956.     int        l;
  3957.     int        c;
  3958.  
  3959.     if (lenp == NULL)
  3960.     len = (int)STRLEN(ptr);
  3961.     else
  3962.     len = *lenp;
  3963.  
  3964.     switch (vcp->vc_type)
  3965.     {
  3966.     case CONV_TO_UTF8:    /* latin1 to utf-8 conversion */
  3967.         retval = alloc(len * 2 + 1);
  3968.         if (retval == NULL)
  3969.         break;
  3970.         d = retval;
  3971.         for (i = 0; i < len; ++i)
  3972.         {
  3973.         if (ptr[i] < 0x80)
  3974.             *d++ = ptr[i];
  3975.         else
  3976.         {
  3977.             *d++ = 0xc0 + ((unsigned)ptr[i] >> 6);
  3978.             *d++ = 0x80 + (ptr[i] & 0x3f);
  3979.         }
  3980.         }
  3981.         *d = NUL;
  3982.         if (lenp != NULL)
  3983.         *lenp = (int)(d - retval);
  3984.         break;
  3985.  
  3986.     case CONV_TO_LATIN1:    /* utf-8 to latin1 conversion */
  3987.         retval = alloc(len + 1);
  3988.         if (retval == NULL)
  3989.         break;
  3990.         d = retval;
  3991.         for (i = 0; i < len; ++i)
  3992.         {
  3993.         l = utf_ptr2len_check(ptr + i);
  3994.         if (l <= 1)
  3995.             *d++ = ptr[i];
  3996.         else
  3997.         {
  3998.             c = utf_ptr2char(ptr + i);
  3999.             if (!utf_iscomposing(c))    /* skip composing chars */
  4000.             {
  4001.             if (c < 0x100)
  4002.                 *d++ = c;
  4003.             else
  4004.             {
  4005.                 *d++ = 0xbf;
  4006.                 if (utf_char2cells(c) > 1)
  4007.                 *d++ = '?';
  4008.             }
  4009.             }
  4010.             i += l - 1;
  4011.         }
  4012.         }
  4013.         *d = NUL;
  4014.         if (lenp != NULL)
  4015.         *lenp = (int)(d - retval);
  4016.         break;
  4017.  
  4018. # ifdef USE_ICONV
  4019.     case CONV_ICONV:    /* conversion with output_conv.vc_fd */
  4020.         retval = iconv_string(vcp->vc_fd, ptr, len);
  4021.         if (retval != NULL && lenp != NULL)
  4022.         *lenp = (int)STRLEN(retval);
  4023. # endif
  4024.     }
  4025.  
  4026.     return retval;
  4027. }
  4028. #endif
  4029.